1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.browsing.ui.common;
14 import java.util.ArrayDeque;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.Deque;
19 import java.util.HashMap;
20 import java.util.HashSet;
25 * The default implementation of <code>EvaluatorData</code>.
28 * <code>Evaluator</code>s can be added by invoking
29 * {@link #addEvaluator(Class, org.simantics.browsing.ui.common.EvaluatorData.Evaluator)
30 * or {@link #addEvaluators(Class, Collection)}. The specified
31 * <code>Evaluator</code> or collection of <code>Evaluator</code>s are bound to
32 * the specified Java class. The reason for such a binding is that the
33 * implementation of {@link #get(Object)} is based on comparing the input object
34 * class to the classes specified to the <code>addEvaluator</code> methods. The
35 * comparison works so that an <code>Evaluator</code> will be added to the
36 * result of {@link #get(Object)} if:
39 * <li>the input object is assignable to the <code>Evaluator</code>'s class
43 * This implementation keeps a <code>Class</code>→<code>Evaluator</code>
44 * cache of previous results thus quickly producing results for a given input
45 * object class after the result has been cached. Note that there is no way to
46 * reset the cache, i.e. this class is intended to be initialized once, used
47 * after that and finally thrown away. Do not add evaluators once in use, they
48 * may or may not be reflected in the results.
51 * @author Tuukka Lehtonen
53 public class EvaluatorDataImpl implements EvaluatorData {
55 private static final boolean DEBUG = false;
58 * Contains only the original evaluator associations made directly by the
59 * client. This is used for initializing the <code>evaluators</code> cache
60 * for different inputs.
62 protected HashMap<Class<?>, Collection<Evaluator>> originals = new HashMap<Class<?>, Collection<Evaluator>>();
65 * A cache that is only modified by
66 * {@link #findAndCacheEvaluatorsForClass(Class)}. This map is not filled in
67 * by client's initialization efforts.
69 protected HashMap<Class<?>, Collection<Evaluator>> evaluators = new HashMap<Class<?>, Collection<Evaluator>>();
71 private Object browseContext;
73 public EvaluatorDataImpl() {
76 public void setBrowseContext(Object browseContext) {
77 this.browseContext = browseContext;
81 public Evaluator newEvaluator() {
82 return new EvaluatorImpl();
85 private synchronized void addEvaluator(HashMap<Class<?>, Collection<Evaluator>> map, Class<?> clazz, Evaluator eval) {
86 Collection<Evaluator> es = map.get(clazz);
88 es = new ArrayList<Evaluator>();
93 // new Exception().printStackTrace();
94 System.out.println("EvaluatorDataImpl: ADDED Evaluator: " + clazz + ": " + eval);
98 private synchronized void addEvaluators(HashMap<Class<?>, Collection<Evaluator>> map, Class<?> clazz, Collection<Evaluator> evals) {
99 Collection<Evaluator> es = map.get(clazz);
101 es = new ArrayList<Evaluator>();
106 System.out.println("EvaluatorDataImpl: ADDED Evaluators: " + clazz + ": " + evals);
109 public synchronized void addEvaluator(Class<?> clazz, Evaluator eval) {
110 addEvaluator(originals, clazz, eval);
113 public synchronized void addEvaluators(Class<?> clazz, Collection<Evaluator> evals) {
114 addEvaluators(originals, clazz, evals);
118 public Collection<Evaluator> get(Object object) {
119 Class<?> clazz = object.getClass();
120 Collection<Evaluator> evaluator = evaluators.get(clazz);
121 if (evaluator != null) {
123 System.out.println("EvaluatorDataImpl: get cached: " + clazz + ": " + evaluator);
127 Collection<Evaluator> evals = findAndCacheEvaluatorsForClass(clazz);
129 System.out.println("EvaluatorDataImpl: get: " + clazz + ": " + evals);
130 if (evals.isEmpty()) {
131 System.out.println("EvaluatorDataImpl: no match, evaluators available:");
132 for (Map.Entry<Class<?>, Collection<Evaluator>> e : evaluators.entrySet()) {
133 if (!e.getValue().isEmpty())
134 System.out.println(" " + e.getKey() + " : " + e.getValue());
141 private synchronized Collection<Evaluator> findAndCacheEvaluatorsForClass(Class<?> clazz) {
143 System.out.println("EvaluatorDataImpl: caching evaluators for " + clazz);
144 Set<Class<?>> usedClasses = new HashSet<Class<?>>();
145 Set<Evaluator> used = new HashSet<Evaluator>();
146 Collection<Evaluator> result = new ArrayList<Evaluator>();
147 Deque<Class<?>> fifo = new ArrayDeque<Class<?>>();
149 while (!fifo.isEmpty()) {
150 Class<?> c = fifo.removeFirst();
151 if (!usedClasses.add(c))
153 Class<?> superClass = c.getSuperclass();
154 if (superClass != null)
155 fifo.addLast(superClass);
156 for (Class<?> i : c.getInterfaces())
158 Collection<Evaluator> evals = originals.get(c);
160 for (Evaluator eval : evals)
164 if (result.isEmpty()) {
165 result = Collections.emptyList();
167 evaluators.put(clazz, result);
172 public Collection<EvaluatorEntry> enumEvaluators() {
173 Collection<EvaluatorEntry> result = new ArrayList<EvaluatorEntry>();
174 for (Map.Entry<Class<?>, Collection<Evaluator>> entry : originals.entrySet()) {
175 result.add(new EvaluatorEntryImpl(entry.getKey(), entry.getValue()));
180 static class EvaluatorEntryImpl implements EvaluatorEntry {
181 private final Class<?> clazz;
182 private final Collection<Evaluator> evaluators;
184 public EvaluatorEntryImpl(Class<?> clazz, Collection<Evaluator> evaluators) {
186 this.evaluators = evaluators;
190 public Class<?> getClazz() {
195 public Collection<Evaluator> getEvaluators() {
200 public String toString() {
201 return "class " + clazz.getSimpleName();
205 @SuppressWarnings("unchecked")
207 public <T> T getBrowseContext() {
208 return (T)browseContext;