X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2FNodeContext.java;fp=bundles%2Forg.simantics.browsing.ui%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2FNodeContext.java;h=c91387c669039e68b1cc893d30dee0fe9213dbc8;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/NodeContext.java b/bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/NodeContext.java new file mode 100644 index 000000000..c91387c66 --- /dev/null +++ b/bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/NodeContext.java @@ -0,0 +1,211 @@ +/******************************************************************************* + * 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; + +import java.util.Arrays; +import java.util.Set; + +import org.eclipse.core.runtime.IAdaptable; + +/** + * A context used to represent a single visible UI item. + * + *

+ * An INodeContext can be initialized to contain multiple constants accessible + * with {@link ConstantKey}s through {@link #getConstant(ConstantKey)}. + *

+ *

+ * It is vital that every instance of INodeContext contains a constant with the + * {@link ConstantKey} {@link BuiltinKeys#INPUT}, since that data is used all + * over the graph explorer framework for resolving labelers, imager, decorators + * and others. + *

+ * + *

+ * INodeContext must implement {@link #equals(Object)} and {@link #hashCode()} + * to enable the graph explorer to work properly. + *

+ * + * @see NodeContextBuilder + * @see NodeContextUtil + */ +public interface NodeContext extends IAdaptable { + + NodeContext[] NONE = new NodeContext[0]; + + /** + * A key interface used for querying constants from INodeContext. Create + * static instances of this interface to create re-usable keys. + * + *

+ * See {@link BuiltinKeys} for standard concrete keys used in the + * implementations + * + * @param type of the value stored with this key. + * + * See NodeContextBuilder + */ + public static interface ConstantKey {} + + /** + * @param the type of the value designated by the specified key + * @param key + * @return the value with the specified key or null there was + * no value for the key + * @throws ClassCastException if the key stored in the node is does not + * match T. This should not happen. + */ + T getConstant(ConstantKey key); + Set> getKeys(); + + /** + * Do not implement this directly, look at {@link PrimitiveQueryKey} and + * {@link QueryKey} instead. + */ + public static interface CacheKey { + /** + * This method must return a unique object that is used to decide which + * QueryProcessor is used to calculate the query result. + * + * The returned value is compared only using object identity (==), not + * equals. + * + * @return the identifier of this processor + */ + Object processorIdenfitier(); + } + + /** + * This key class is used for non-leaf queries that only functionally + * perform other queries to produce their result. + * + *

+ * These are always cleared (invalidated) or updated inside the query + * manager. The methods available in {@link NodeQueryManager} are the only + * methods within the query system that the query implementation can use. It + * cannot perform lazy evaluation. + * + * @see NodeQueryManager + * @see NodeQueryProcessor + */ + public static abstract class QueryKey implements CacheKey { + @Override + public Object processorIdenfitier() { + return this; + } + } + + /** + * Primitive query keys are used only for leaf queries that do not + * perform more queries. Only these queries are updated from external + * sources that are registered through + * {@link GraphExplorer#setDataSource(DataSource)}. + * + *

+ * The difference between these queries and {@link QueryKey} queries is that + * these queries cannot do any further queries, which is already prohibited + * by the only available interface, {@link PrimitiveQueryUpdater}. Instead + * these queries can use the + * {@link PrimitiveQueryUpdater#scheduleReplace(NodeContext, PrimitiveQueryKey, T)} + * method to store concrete values within the query manager and possibly + * replace them later when lazy evaluation has completed. Replacing a lazily + * evaluated result will automatically invalidate all queries depending on + * this result, also causing the UI to respond to the changes. + * + * @see PrimitiveQueryUpdater + * @see PrimitiveQueryProcessor + */ + public static abstract class PrimitiveQueryKey implements CacheKey { + @Override + public Object processorIdenfitier() { + return this; + } + } + + /** + * This primitive query key implementation can be used for passing other + * parameters to primitive queries besides the input {@link NodeContext}. + * + *

+ * The extending class must implement the getKeyName() method to provide a + * human-readable name for the key that is used in the default + * {@link #toString()} implementation. + * + *

+ * This class uses the class object as the default processor identifier + * object (see {@link CacheKey#processorIdenfitier()}. This should work + * out-of-the-box for most cases and need not be customized. + */ + public abstract static class ParametrizedPrimitiveQueryKey extends PrimitiveQueryKey { + private final Object[] parameters; + private final int hash; + protected ParametrizedPrimitiveQueryKey(Object ... parameters) { + this.parameters = parameters; + this.hash = hash(); + } + + @Override + public Object processorIdenfitier() { + return getClass(); + } + + @Override + public String toString() { + return getKeyName() + Arrays.toString(parameters); + } + + /** + * @param

the assumed type of the parameter object + * @param index the index of the reqeusted parameter + * @return the parameter with the specified index + * @throws ClassCastException if the key stored in the node is does not + * match P. + * @throws ArrayIndexOutOfBoundsException if a parameter with the + * specified index is not availble. + */ + @SuppressWarnings("unchecked") + public

P getParameter(int index) { + return (P) parameters[index]; + } + + public abstract String getKeyName(); + + /** + * Calculates the hash value for this key. The default implementation is + * based on the hash of the actual key class and the hash of the + * parameters. + * + * @return the hash value + */ + protected int hash() { + return getClass().hashCode() * 31 + Arrays.hashCode(parameters); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ParametrizedPrimitiveQueryKey o = (ParametrizedPrimitiveQueryKey) obj; + return Arrays.equals(parameters, o.parameters); + } + + @Override + public int hashCode() { + return hash; + } + } + +}