/******************************************************************************* * 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; } } }