-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.browsing.ui.common;\r
-\r
-import java.util.ArrayDeque;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Deque;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-/**\r
- * The default implementation of <code>EvaluatorData</code>.\r
- * \r
- * <p>\r
- * <code>Evaluator</code>s can be added by invoking\r
- * {@link #addEvaluator(Class, org.simantics.browsing.ui.common.EvaluatorData.Evaluator)\r
- * or {@link #addEvaluators(Class, Collection)}. The specified\r
- * <code>Evaluator</code> or collection of <code>Evaluator</code>s are bound to\r
- * the specified Java class. The reason for such a binding is that the\r
- * implementation of {@link #get(Object)} is based on comparing the input object\r
- * class to the classes specified to the <code>addEvaluator</code> methods. The\r
- * comparison works so that an <code>Evaluator</code> will be added to the\r
- * result of {@link #get(Object)} if:\r
- * </p>\r
- * <ul>\r
- * <li>the input object is assignable to the <code>Evaluator</code>'s class\r
- * </ul>\r
- * \r
- * <p>\r
- * This implementation keeps a <code>Class</code>→<code>Evaluator</code>\r
- * cache of previous results thus quickly producing results for a given input\r
- * object class after the result has been cached. Note that there is no way to\r
- * reset the cache, i.e. this class is intended to be initialized once, used\r
- * after that and finally thrown away. Do not add evaluators once in use, they\r
- * may or may not be reflected in the results.\r
- * </p>\r
- * \r
- * @author Tuukka Lehtonen\r
- */\r
-public class EvaluatorDataImpl implements EvaluatorData {\r
-\r
- private static final boolean DEBUG = false;\r
-\r
- /**\r
- * Contains only the original evaluator associations made directly by the\r
- * client. This is used for initializing the <code>evaluators</code> cache\r
- * for different inputs.\r
- */\r
- protected HashMap<Class<?>, Collection<Evaluator>> originals = new HashMap<Class<?>, Collection<Evaluator>>();\r
-\r
- /**\r
- * A cache that is only modified by\r
- * {@link #findAndCacheEvaluatorsForClass(Class)}. This map is not filled in\r
- * by client's initialization efforts.\r
- */\r
- protected HashMap<Class<?>, Collection<Evaluator>> evaluators = new HashMap<Class<?>, Collection<Evaluator>>();\r
-\r
- private Object browseContext;\r
- \r
- public EvaluatorDataImpl() {\r
- }\r
- \r
- public void setBrowseContext(Object browseContext) {\r
- this.browseContext = browseContext;\r
- }\r
- \r
- @Override\r
- public Evaluator newEvaluator() {\r
- return new EvaluatorImpl();\r
- }\r
-\r
- private synchronized void addEvaluator(HashMap<Class<?>, Collection<Evaluator>> map, Class<?> clazz, Evaluator eval) {\r
- Collection<Evaluator> es = map.get(clazz);\r
- if (es == null) {\r
- es = new ArrayList<Evaluator>();\r
- map.put(clazz, es);\r
- }\r
- es.add(eval);\r
- if (DEBUG) {\r
-// new Exception().printStackTrace();\r
- System.out.println("EvaluatorDataImpl: ADDED Evaluator: " + clazz + ": " + eval);\r
- }\r
- }\r
-\r
- private synchronized void addEvaluators(HashMap<Class<?>, Collection<Evaluator>> map, Class<?> clazz, Collection<Evaluator> evals) {\r
- Collection<Evaluator> es = map.get(clazz);\r
- if (es == null) {\r
- es = new ArrayList<Evaluator>();\r
- map.put(clazz, es);\r
- }\r
- es.addAll(evals);\r
- if (DEBUG)\r
- System.out.println("EvaluatorDataImpl: ADDED Evaluators: " + clazz + ": " + evals);\r
- }\r
-\r
- public synchronized void addEvaluator(Class<?> clazz, Evaluator eval) {\r
- addEvaluator(originals, clazz, eval);\r
- }\r
-\r
- public synchronized void addEvaluators(Class<?> clazz, Collection<Evaluator> evals) {\r
- addEvaluators(originals, clazz, evals);\r
- }\r
-\r
- @Override\r
- public Collection<Evaluator> get(Object object) {\r
- Class<?> clazz = object.getClass();\r
- Collection<Evaluator> evaluator = evaluators.get(clazz);\r
- if (evaluator != null) {\r
- if (DEBUG)\r
- System.out.println("EvaluatorDataImpl: get cached: " + clazz + ": " + evaluator);\r
- return evaluator;\r
- }\r
-\r
- Collection<Evaluator> evals = findAndCacheEvaluatorsForClass(clazz);\r
- if (DEBUG) {\r
- System.out.println("EvaluatorDataImpl: get: " + clazz + ": " + evals);\r
- if (evals.isEmpty()) {\r
- System.out.println("EvaluatorDataImpl: no match, evaluators available:");\r
- for (Map.Entry<Class<?>, Collection<Evaluator>> e : evaluators.entrySet()) {\r
- if (!e.getValue().isEmpty())\r
- System.out.println(" " + e.getKey() + " : " + e.getValue());\r
- }\r
- }\r
- }\r
- return evals;\r
- }\r
-\r
- private synchronized Collection<Evaluator> findAndCacheEvaluatorsForClass(Class<?> clazz) {\r
- if (DEBUG)\r
- System.out.println("EvaluatorDataImpl: caching evaluators for " + clazz);\r
- Set<Class<?>> usedClasses = new HashSet<Class<?>>();\r
- Set<Evaluator> used = new HashSet<Evaluator>();\r
- Collection<Evaluator> result = new ArrayList<Evaluator>();\r
- Deque<Class<?>> fifo = new ArrayDeque<Class<?>>();\r
- fifo.add(clazz);\r
- while (!fifo.isEmpty()) {\r
- Class<?> c = fifo.removeFirst();\r
- if (!usedClasses.add(c))\r
- continue;\r
- Class<?> superClass = c.getSuperclass();\r
- if (superClass != null)\r
- fifo.addLast(superClass);\r
- for (Class<?> i : c.getInterfaces())\r
- fifo.addLast(i);\r
- Collection<Evaluator> evals = originals.get(c);\r
- if (evals != null)\r
- for (Evaluator eval : evals)\r
- if (used.add(eval))\r
- result.add(eval);\r
- }\r
- if (result.isEmpty()) {\r
- result = Collections.emptyList();\r
- }\r
- evaluators.put(clazz, result);\r
- return result;\r
- }\r
-\r
- @Override\r
- public Collection<EvaluatorEntry> enumEvaluators() {\r
- Collection<EvaluatorEntry> result = new ArrayList<EvaluatorEntry>();\r
- for (Map.Entry<Class<?>, Collection<Evaluator>> entry : originals.entrySet()) {\r
- result.add(new EvaluatorEntryImpl(entry.getKey(), entry.getValue()));\r
- }\r
- return result;\r
- }\r
-\r
- static class EvaluatorEntryImpl implements EvaluatorEntry {\r
- private final Class<?> clazz;\r
- private final Collection<Evaluator> evaluators;\r
-\r
- public EvaluatorEntryImpl(Class<?> clazz, Collection<Evaluator> evaluators) {\r
- this.clazz = clazz;\r
- this.evaluators = evaluators;\r
- }\r
-\r
- @Override\r
- public Class<?> getClazz() {\r
- return clazz;\r
- }\r
-\r
- @Override\r
- public Collection<Evaluator> getEvaluators() {\r
- return evaluators;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return "class " + clazz.getSimpleName();\r
- }\r
- }\r
-\r
- @Override\r
- public <T> T getBrowseContext() {\r
- return (T)browseContext;\r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.browsing.ui.common;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The default implementation of <code>EvaluatorData</code>.
+ *
+ * <p>
+ * <code>Evaluator</code>s can be added by invoking
+ * {@link #addEvaluator(Class, org.simantics.browsing.ui.common.EvaluatorData.Evaluator)
+ * or {@link #addEvaluators(Class, Collection)}. The specified
+ * <code>Evaluator</code> or collection of <code>Evaluator</code>s are bound to
+ * the specified Java class. The reason for such a binding is that the
+ * implementation of {@link #get(Object)} is based on comparing the input object
+ * class to the classes specified to the <code>addEvaluator</code> methods. The
+ * comparison works so that an <code>Evaluator</code> will be added to the
+ * result of {@link #get(Object)} if:
+ * </p>
+ * <ul>
+ * <li>the input object is assignable to the <code>Evaluator</code>'s class
+ * </ul>
+ *
+ * <p>
+ * This implementation keeps a <code>Class</code>→<code>Evaluator</code>
+ * cache of previous results thus quickly producing results for a given input
+ * object class after the result has been cached. Note that there is no way to
+ * reset the cache, i.e. this class is intended to be initialized once, used
+ * after that and finally thrown away. Do not add evaluators once in use, they
+ * may or may not be reflected in the results.
+ * </p>
+ *
+ * @author Tuukka Lehtonen
+ */
+public class EvaluatorDataImpl implements EvaluatorData {
+
+ private static final boolean DEBUG = false;
+
+ /**
+ * Contains only the original evaluator associations made directly by the
+ * client. This is used for initializing the <code>evaluators</code> cache
+ * for different inputs.
+ */
+ protected HashMap<Class<?>, Collection<Evaluator>> originals = new HashMap<Class<?>, Collection<Evaluator>>();
+
+ /**
+ * A cache that is only modified by
+ * {@link #findAndCacheEvaluatorsForClass(Class)}. This map is not filled in
+ * by client's initialization efforts.
+ */
+ protected HashMap<Class<?>, Collection<Evaluator>> evaluators = new HashMap<Class<?>, Collection<Evaluator>>();
+
+ private Object browseContext;
+
+ public EvaluatorDataImpl() {
+ }
+
+ public void setBrowseContext(Object browseContext) {
+ this.browseContext = browseContext;
+ }
+
+ @Override
+ public Evaluator newEvaluator() {
+ return new EvaluatorImpl();
+ }
+
+ private synchronized void addEvaluator(HashMap<Class<?>, Collection<Evaluator>> map, Class<?> clazz, Evaluator eval) {
+ Collection<Evaluator> es = map.get(clazz);
+ if (es == null) {
+ es = new ArrayList<Evaluator>();
+ map.put(clazz, es);
+ }
+ es.add(eval);
+ if (DEBUG) {
+// new Exception().printStackTrace();
+ System.out.println("EvaluatorDataImpl: ADDED Evaluator: " + clazz + ": " + eval);
+ }
+ }
+
+ private synchronized void addEvaluators(HashMap<Class<?>, Collection<Evaluator>> map, Class<?> clazz, Collection<Evaluator> evals) {
+ Collection<Evaluator> es = map.get(clazz);
+ if (es == null) {
+ es = new ArrayList<Evaluator>();
+ map.put(clazz, es);
+ }
+ es.addAll(evals);
+ if (DEBUG)
+ System.out.println("EvaluatorDataImpl: ADDED Evaluators: " + clazz + ": " + evals);
+ }
+
+ public synchronized void addEvaluator(Class<?> clazz, Evaluator eval) {
+ addEvaluator(originals, clazz, eval);
+ }
+
+ public synchronized void addEvaluators(Class<?> clazz, Collection<Evaluator> evals) {
+ addEvaluators(originals, clazz, evals);
+ }
+
+ @Override
+ public Collection<Evaluator> get(Object object) {
+ Class<?> clazz = object.getClass();
+ Collection<Evaluator> evaluator = evaluators.get(clazz);
+ if (evaluator != null) {
+ if (DEBUG)
+ System.out.println("EvaluatorDataImpl: get cached: " + clazz + ": " + evaluator);
+ return evaluator;
+ }
+
+ Collection<Evaluator> evals = findAndCacheEvaluatorsForClass(clazz);
+ if (DEBUG) {
+ System.out.println("EvaluatorDataImpl: get: " + clazz + ": " + evals);
+ if (evals.isEmpty()) {
+ System.out.println("EvaluatorDataImpl: no match, evaluators available:");
+ for (Map.Entry<Class<?>, Collection<Evaluator>> e : evaluators.entrySet()) {
+ if (!e.getValue().isEmpty())
+ System.out.println(" " + e.getKey() + " : " + e.getValue());
+ }
+ }
+ }
+ return evals;
+ }
+
+ private synchronized Collection<Evaluator> findAndCacheEvaluatorsForClass(Class<?> clazz) {
+ if (DEBUG)
+ System.out.println("EvaluatorDataImpl: caching evaluators for " + clazz);
+ Set<Class<?>> usedClasses = new HashSet<Class<?>>();
+ Set<Evaluator> used = new HashSet<Evaluator>();
+ Collection<Evaluator> result = new ArrayList<Evaluator>();
+ Deque<Class<?>> fifo = new ArrayDeque<Class<?>>();
+ fifo.add(clazz);
+ while (!fifo.isEmpty()) {
+ Class<?> c = fifo.removeFirst();
+ if (!usedClasses.add(c))
+ continue;
+ Class<?> superClass = c.getSuperclass();
+ if (superClass != null)
+ fifo.addLast(superClass);
+ for (Class<?> i : c.getInterfaces())
+ fifo.addLast(i);
+ Collection<Evaluator> evals = originals.get(c);
+ if (evals != null)
+ for (Evaluator eval : evals)
+ if (used.add(eval))
+ result.add(eval);
+ }
+ if (result.isEmpty()) {
+ result = Collections.emptyList();
+ }
+ evaluators.put(clazz, result);
+ return result;
+ }
+
+ @Override
+ public Collection<EvaluatorEntry> enumEvaluators() {
+ Collection<EvaluatorEntry> result = new ArrayList<EvaluatorEntry>();
+ for (Map.Entry<Class<?>, Collection<Evaluator>> entry : originals.entrySet()) {
+ result.add(new EvaluatorEntryImpl(entry.getKey(), entry.getValue()));
+ }
+ return result;
+ }
+
+ static class EvaluatorEntryImpl implements EvaluatorEntry {
+ private final Class<?> clazz;
+ private final Collection<Evaluator> evaluators;
+
+ public EvaluatorEntryImpl(Class<?> clazz, Collection<Evaluator> evaluators) {
+ this.clazz = clazz;
+ this.evaluators = evaluators;
+ }
+
+ @Override
+ public Class<?> getClazz() {
+ return clazz;
+ }
+
+ @Override
+ public Collection<Evaluator> getEvaluators() {
+ return evaluators;
+ }
+
+ @Override
+ public String toString() {
+ return "class " + clazz.getSimpleName();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getBrowseContext() {
+ return (T)browseContext;
+ }
+
+}