]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/processors/AbstractFactoryResolverQueryProcessor.java
99d7583400f0a964e2e54f8f6e50c87dbf6570f4
[simantics/platform.git] / bundles / org.simantics.browsing.ui.common / src / org / simantics / browsing / ui / common / processors / AbstractFactoryResolverQueryProcessor.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.browsing.ui.common.processors;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.Collections;\r
17 \r
18 import org.simantics.browsing.ui.BuiltinKeys;\r
19 import org.simantics.browsing.ui.NodeContext;\r
20 import org.simantics.browsing.ui.NodeContext.QueryKey;\r
21 import org.simantics.browsing.ui.NodeQueryManager;\r
22 import org.simantics.browsing.ui.Tester;\r
23 import org.simantics.browsing.ui.common.EvaluatorData;\r
24 import org.simantics.browsing.ui.common.EvaluatorData.Evaluator;\r
25 import org.simantics.browsing.ui.common.EvaluatorData.EvaluatorTree;\r
26 import org.simantics.browsing.ui.common.Preference;\r
27 import org.simantics.utils.datastructures.collections.CollectionUtils;\r
28 \r
29 /**\r
30  * A base class for query processors that resolve a set of suitable factory\r
31  * classes of a kind for a given INodeContext.\r
32  * \r
33  * <p>\r
34  * The purpose of this class is to generically implement a basic logic for\r
35  * resolving available factories (viewpoint/labeler/labeldecorator/comparator)\r
36  * any given input. The implementation works based on an\r
37  * <code>EvaluatorData</code> instance that is specified externally.The logic is\r
38  * as follows:\r
39  * </p>\r
40  * <ol>\r
41  * <li>Get all possible <code>Evaluator</code>s from the externally specified\r
42  * EvaluatorData (see {@link EvaluatorData#get(Object)}).</li>\r
43  * <li>For each <code>Evaluator</code>:\r
44  * <ul>\r
45  * <li>Walk the <code>EvaluatorTree</code> structure returned by\r
46  * {@link #getEvaluatorTree(Evaluator)} while checking at each node whether the\r
47  * {@link Tester} returned by {@link EvaluatorTree#getTester()} returns\r
48  * <code>true</code>. If <code>true</code> is returned, the factories at this\r
49  * node ({@link EvaluatorTree#getAcceptedFactories()}) are added to the result\r
50  * and all children ({@link EvaluatorTree#getChildren()}) are recursively\r
51  * walked. Otherwise if <code>false</code> is returned, the walking of the\r
52  * subtree will end.</li>\r
53  * </ul>\r
54  * </li>\r
55  * <li>Sort the results in descending preference order, larger number equals\r
56  * higher preference</li>\r
57  * </ol>\r
58  * \r
59  * <p>\r
60  * This class intended for sub-classing, please implement these methods:\r
61  * <ul>\r
62  * <li><code>getEvaluatorTree(Evaluator)</code> - return the appropriate\r
63  * <code>EvaluatorTree</code> of the specified <code>Evaluator</code></li>\r
64  * </ul>\r
65  * \r
66  * @author Tuukka Lehtonen\r
67  * \r
68  * @param <Factory> the factory type to use\r
69  * \r
70  * @see ComparableFactoryResolver\r
71  * @see LabelDecoratorFactoryResolver\r
72  * @see ImageDecoratorFactoryResolver\r
73  * @see LabelerFactoryResolver\r
74  * @see ImagerFactoryResolver\r
75  * @see ViewpointFactoryResolver\r
76  */\r
77 public abstract class AbstractFactoryResolverQueryProcessor<Factory> extends AbstractNodeQueryProcessor<Collection<Factory>> {\r
78 \r
79     private final EvaluatorData data;\r
80     private final QueryKey<Collection<Factory>> identifier;\r
81 \r
82     public AbstractFactoryResolverQueryProcessor(EvaluatorData data, QueryKey<Collection<Factory>> identifier) {\r
83         this.data = data;\r
84         this.identifier = identifier;\r
85     }\r
86 \r
87     @Override\r
88     public QueryKey<Collection<Factory>> getIdentifier() {\r
89         return identifier;\r
90     }\r
91 \r
92     @Override\r
93     public Collection<Factory> query(final NodeQueryManager manager, final NodeContext context) {\r
94         assert context != null;\r
95 \r
96         Object input = context.getConstant(BuiltinKeys.INPUT);\r
97         assert input != null;\r
98 \r
99         Collection<Evaluator> evals = data.get(input);\r
100         if (evals.isEmpty())\r
101             return Collections.emptyList();\r
102 \r
103         ArrayList<Preference<Factory>> factories = new ArrayList<Preference<Factory>>(4);\r
104         for (Evaluator eval : evals) {\r
105             evaluateTree(manager, context, getEvaluatorTree(eval), factories);\r
106         }\r
107 \r
108         if (factories.isEmpty())\r
109             return Collections.emptyList();\r
110 \r
111         if (factories.size() > 1)\r
112             Collections.sort(factories);\r
113 \r
114         ArrayList<Factory> result = new ArrayList<Factory>(factories.size());\r
115         for (Preference<Factory> p : factories) {\r
116             result.add(p.object);\r
117         }\r
118 \r
119         return result;\r
120     }\r
121 \r
122     protected void evaluateTree(NodeQueryManager manager, NodeContext context, EvaluatorTree<Factory> tree, Collection<Preference<Factory>> result) {\r
123         Tester test = tree.getTester();\r
124 \r
125         if (test.test(manager, context)) {\r
126             CollectionUtils.checkedAdd(tree.getAcceptedFactories(), result);\r
127 \r
128             Collection<EvaluatorTree<Factory>> children = tree.getChildren();\r
129             if (children == null)\r
130                 return;\r
131             for (EvaluatorTree<Factory> e : children) {\r
132                 evaluateTree(manager, context, e, result);\r
133             }\r
134         }\r
135     }\r
136 \r
137     /**\r
138      * @param evaluator\r
139      * @return\r
140      */\r
141     protected abstract EvaluatorTree<Factory> getEvaluatorTree(Evaluator evaluator);\r
142 \r
143 }\r