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;
14 import java.util.Arrays;
17 import org.eclipse.core.runtime.IAdaptable;
20 * A context used to represent a single visible UI item.
23 * An INodeContext can be initialized to contain multiple constants accessible
24 * with {@link ConstantKey}s through {@link #getConstant(ConstantKey)}.
27 * It is vital that every instance of INodeContext contains a constant with the
28 * {@link ConstantKey} {@link BuiltinKeys#INPUT}, since that data is used all
29 * over the graph explorer framework for resolving labelers, imager, decorators
34 * INodeContext must implement {@link #equals(Object)} and {@link #hashCode()}
35 * to enable the graph explorer to work properly.
38 * @see NodeContextBuilder
39 * @see NodeContextUtil
41 public interface NodeContext extends IAdaptable {
43 NodeContext[] NONE = new NodeContext[0];
46 * A key interface used for querying constants from INodeContext. Create
47 * static instances of this interface to create re-usable keys.
50 * See {@link BuiltinKeys} for standard concrete keys used in the
53 * @param <T> type of the value stored with this key.
55 * See NodeContextBuilder
57 public static interface ConstantKey<T> {}
60 * @param <T> the type of the value designated by the specified key
62 * @return the value with the specified key or <code>null</code> there was
63 * no value for the key
64 * @throws ClassCastException if the key stored in the node is does not
65 * match T. This should not happen.
67 <T> T getConstant(ConstantKey<T> key);
68 Set<ConstantKey<?>> getKeys();
71 * Do not implement this directly, look at {@link PrimitiveQueryKey} and
72 * {@link QueryKey} instead.
74 public static interface CacheKey<T> {
76 * This method must return a unique object that is used to decide which
77 * QueryProcessor is used to calculate the query result.
79 * The returned value is compared only using object identity (==), not
82 * @return the identifier of this processor
84 Object processorIdenfitier();
88 * This key class is used for <i>non-leaf</i> queries that only functionally
89 * perform other queries to produce their result.
92 * These are always cleared (invalidated) or updated inside the query
93 * manager. The methods available in {@link NodeQueryManager} are the only
94 * methods within the query system that the query implementation can use. It
95 * cannot perform lazy evaluation.
97 * @see NodeQueryManager
98 * @see NodeQueryProcessor
100 public static abstract class QueryKey<T> implements CacheKey<T> {
102 public Object processorIdenfitier() {
108 * Primitive query keys are used only for <i>leaf</i> queries that do not
109 * perform more queries. Only these queries are updated from external
110 * sources that are registered through
111 * {@link GraphExplorer#setDataSource(DataSource)}.
114 * The difference between these queries and {@link QueryKey} queries is that
115 * these queries cannot do any further queries, which is already prohibited
116 * by the only available interface, {@link PrimitiveQueryUpdater}. Instead
117 * these queries can use the
118 * {@link PrimitiveQueryUpdater#scheduleReplace(NodeContext, PrimitiveQueryKey, T)}
119 * method to store concrete values within the query manager and possibly
120 * replace them later when lazy evaluation has completed. Replacing a lazily
121 * evaluated result will automatically invalidate all queries depending on
122 * this result, also causing the UI to respond to the changes.
124 * @see PrimitiveQueryUpdater
125 * @see PrimitiveQueryProcessor
127 public static abstract class PrimitiveQueryKey<T> implements CacheKey<T> {
129 public Object processorIdenfitier() {
135 * This primitive query key implementation can be used for passing other
136 * parameters to primitive queries besides the input {@link NodeContext}.
139 * The extending class must implement the getKeyName() method to provide a
140 * human-readable name for the key that is used in the default
141 * {@link #toString()} implementation.
144 * This class uses the class object as the default processor identifier
145 * object (see {@link CacheKey#processorIdenfitier()}. This should work
146 * out-of-the-box for most cases and need not be customized.
148 public abstract static class ParametrizedPrimitiveQueryKey<T> extends PrimitiveQueryKey<T> {
149 private final Object[] parameters;
150 private final int hash;
151 protected ParametrizedPrimitiveQueryKey(Object ... parameters) {
152 this.parameters = parameters;
157 public Object processorIdenfitier() {
162 public String toString() {
163 return getKeyName() + Arrays.toString(parameters);
167 * @param <P> the assumed type of the parameter object
168 * @param index the index of the reqeusted parameter
169 * @return the parameter with the specified index
170 * @throws ClassCastException if the key stored in the node is does not
172 * @throws ArrayIndexOutOfBoundsException if a parameter with the
173 * specified index is not availble.
175 @SuppressWarnings("unchecked")
176 public <P> P getParameter(int index) {
177 return (P) parameters[index];
180 public abstract String getKeyName();
183 * Calculates the hash value for this key. The default implementation is
184 * based on the hash of the actual key class and the hash of the
187 * @return the hash value
189 protected int hash() {
190 return getClass().hashCode() * 31 + Arrays.hashCode(parameters);
194 public boolean equals(Object obj) {
199 if (getClass() != obj.getClass())
201 ParametrizedPrimitiveQueryKey<?> o = (ParametrizedPrimitiveQueryKey<?>) obj;
202 return Arrays.equals(parameters, o.parameters);
206 public int hashCode() {