]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/NodeContextBuilder.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.browsing.ui.common / src / org / simantics / browsing / ui / common / NodeContextBuilder.java
diff --git a/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/NodeContextBuilder.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/NodeContextBuilder.java
new file mode 100644 (file)
index 0000000..c8083e1
--- /dev/null
@@ -0,0 +1,298 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.browsing.ui.common;\r
+\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.simantics.browsing.ui.BuiltinKeys;\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.NodeContext.ConstantKey;\r
+import org.simantics.browsing.ui.content.Viewpoint;\r
+import org.simantics.utils.datastructures.ArrayMap;\r
+\r
+/**\r
+ * Use this class in {@link Viewpoint}, and particularly\r
+ * {@link Viewpoint#getChildren()} implementations to construct new INodeContext\r
+ * instances.\r
+ * \r
+ * @author Antti Villberg\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public final class NodeContextBuilder {\r
+\r
+    private static Set<ConstantKey<?>> SINGLE_INPUT_KEYS =\r
+        Collections.<ConstantKey<?>> singleton(BuiltinKeys.INPUT);\r
+\r
+    MapNodeContext context;\r
+\r
+    private static class InputNodeContext implements NodeContext {\r
+\r
+        final Object input;\r
+\r
+        private InputNodeContext(Object input) {\r
+            this.input = input;\r
+        }\r
+\r
+        @SuppressWarnings({ "unchecked", "rawtypes" })\r
+        @Override\r
+        public Object getAdapter(Class adapter) {\r
+            if (NodeContext.class.equals(adapter))\r
+                return this;\r
+            if (input != null) {\r
+                if (adapter.isAssignableFrom(input.getClass()))\r
+                    return input;\r
+                if (input instanceof IAdaptable)\r
+                    return ((IAdaptable) input).getAdapter(adapter);\r
+            }\r
+            return null;\r
+        }\r
+\r
+        @SuppressWarnings("unchecked")\r
+        @Override\r
+        public <T> T getConstant(ConstantKey<T> key) {\r
+            return key == BuiltinKeys.INPUT ? (T) input : null;\r
+        }\r
+\r
+        @Override\r
+        public Set<ConstantKey<?>> getKeys() {\r
+            return SINGLE_INPUT_KEYS;\r
+        }\r
+\r
+        @Override\r
+        public int hashCode() {\r
+            return ((input == null) ? 0 : input.hashCode());\r
+        }\r
+\r
+        @Override\r
+        public boolean equals(Object obj) {\r
+            if (this == obj)\r
+                return true;\r
+            if (obj == null)\r
+                return false;\r
+            if (getClass() != obj.getClass())\r
+                return false;\r
+            InputNodeContext other = (InputNodeContext) obj;\r
+            if (input == null) {\r
+                if (other.input != null)\r
+                    return false;\r
+            } else if (!input.equals(other.input))\r
+                return false;\r
+            return true;\r
+        }\r
+\r
+        @Override\r
+        public String toString() {\r
+            return "InputNodeContext(" + hashCode() + ") [" + input + "]";\r
+        }\r
+    }\r
+\r
+    public static class MapNodeContext implements NodeContext {\r
+\r
+        private Map<ConstantKey<?>, Object> data;\r
+        private int hash;\r
+\r
+        private MapNodeContext() {\r
+        }\r
+\r
+        void makeHash() {\r
+            this.hash = (data == null) ? 0 : data.hashCode();\r
+        }\r
+\r
+        @SuppressWarnings({ "unchecked", "rawtypes" })\r
+        @Override\r
+        public Object getAdapter(Class adapter) {\r
+            if (NodeContext.class.equals(adapter))\r
+                return this;\r
+            Object input = data.get(BuiltinKeys.INPUT);\r
+            if (input != null) {\r
+                if (adapter.isAssignableFrom(input.getClass()))\r
+                    return input;\r
+                if (input instanceof IAdaptable)\r
+                    return ((IAdaptable) input).getAdapter(adapter);\r
+            }\r
+            return null;\r
+        }\r
+\r
+        @SuppressWarnings("unchecked")\r
+        @Override\r
+        public <T> T getConstant(ConstantKey<T> key) {\r
+            return data != null ? (T) data.get(key) : null;\r
+        }\r
+\r
+        @Override\r
+        public Set<ConstantKey<?>> getKeys() {\r
+            return data.keySet();\r
+        }\r
+\r
+        @Override\r
+        public int hashCode() {\r
+            return hash;\r
+        }\r
+\r
+        @Override\r
+        public boolean equals(Object obj) {\r
+            if (this == obj)\r
+                return true;\r
+            if (obj == null)\r
+                return false;\r
+            if (getClass() != obj.getClass())\r
+                return false;\r
+            MapNodeContext other = (MapNodeContext) obj;\r
+            if (data == null) {\r
+                if (other.data != null)\r
+                    return false;\r
+            } else if (!data.equals(other.data))\r
+                return false;\r
+            return true;\r
+        }\r
+\r
+        @Override\r
+        public String toString() {\r
+            return "MapNodeContext(" + hashCode() + ") [" + (data != null ? data : "") + "]";\r
+        }\r
+    }\r
+\r
+    public NodeContextBuilder() {\r
+        this.context = new MapNodeContext();\r
+    }\r
+\r
+    public <T> NodeContextBuilder define(ConstantKey<T> key, T value) {\r
+        if (context.data == null)\r
+            context.data = new HashMap<ConstantKey<?>, Object>();\r
+        context.data.put(key, value);\r
+        return this;\r
+    }\r
+\r
+    public NodeContext createContext() {\r
+        context.makeHash();\r
+        return context;\r
+    }\r
+\r
+    /**\r
+     * A special case builder for an INodeContext that will only take one\r
+     * (key,value) pair and insert that into the built INodeContext.\r
+     * \r
+     * <p>\r
+     * This method works around the need to create NodeContextBuilder instances.\r
+     * </p>\r
+     * \r
+     * <p>\r
+     * Notice that your input key and value must properly implement\r
+     * <code>equals</code> and <code>hashCode</code> in order for\r
+     * GraphExplorer's automatic node expansion state tracking to work.\r
+     * </p>\r
+     * \r
+     * @param key\r
+     * @param value\r
+     * @return an INodeContext containing a single constant as specified by\r
+     *         <code>key</code> and <code>value</code>\r
+     */\r
+    public static <T> NodeContext buildWithSingleData(ConstantKey<T> key, T value) {\r
+        MapNodeContext context = new MapNodeContext();\r
+        context.data = Collections.<ConstantKey<?>, Object>singletonMap(key, value);\r
+        context.makeHash();\r
+        return context;\r
+    }\r
+\r
+    /**\r
+     * A generic case builder for an INodeContext that will take as many\r
+     * (key,value) pairs as it is given and insert all of them into a map\r
+     * that is backing the built INodeContext implementation.\r
+     * \r
+     * <p>\r
+     * This method works around the need to create NodeContextBuilder instances.\r
+     * </p>\r
+     * \r
+     * <p>\r
+     * Notice that your input keys and values must properly implement\r
+     * <code>equals</code> and <code>hashCode</code> in order for\r
+     * GraphExplorer's automatic node expansion state tracking to work.\r
+     * </p>\r
+     * \r
+     * @param keyValuePairs\r
+     * @return an INodeContext containing the specified key,value pairs as its\r
+     *         constants\r
+     */\r
+    public static <T> NodeContext buildWithData(Object... keyValuePairs) {\r
+        assert keyValuePairs.length % 2 == 0;\r
+        MapNodeContext context = new MapNodeContext();\r
+        int size = keyValuePairs.length;\r
+        Map<ConstantKey<?>, Object> map = new HashMap<ConstantKey<?>, Object>(size);\r
+\r
+        for (int i = 0; i < keyValuePairs.length; i += 2) {\r
+            map.put((ConstantKey<?>) keyValuePairs[i], keyValuePairs[i+1]);\r
+        }\r
+\r
+        context.data = map;\r
+        context.makeHash();\r
+        return context;\r
+    }\r
+\r
+    /**\r
+     * A generic case builder for an INodeContext that will take as many\r
+     * (key,value) pairs as it is given and insert all of them into a map that\r
+     * is backing the built INodeContext implementation. This method takes the\r
+     * keys and values separately, which allows the use of {@link ArrayMap} that\r
+     * provides a space-optimized Map implementation. Note that the key set of\r
+     * an {@link ArrayMap} is immutable.\r
+     * \r
+     * <p>\r
+     * This method works around the need to create NodeContextBuilder instances.\r
+     * </p>\r
+     * \r
+     * <p>\r
+     * Notice that your input keys and values must properly implement\r
+     * <code>equals</code> and <code>hashCode</code> in order for\r
+     * GraphExplorer's automatic node expansion state tracking to work.\r
+     * </p>\r
+     * \r
+     * @param keys the keys of the map, must equal values array in size\r
+     * @param values the values of the map, must equal keys array in size\r
+     * @return a <code>NodeContext</code> containing the specified key,value\r
+     *         pairs as its constants\r
+     */\r
+    public static <T> NodeContext buildWithData(ConstantKey<?>[] keys, Object[] values) {\r
+        assert keys.length == values.length;\r
+        MapNodeContext context = new MapNodeContext();\r
+        Map<ConstantKey<?>, Object> map = new ArrayMap<ConstantKey<?>, Object>(keys, values);\r
+        context.data = map;\r
+        context.makeHash();\r
+        return context;\r
+    }\r
+\r
+    /**\r
+     * A special case builder for an INodeContext that will only take one\r
+     * (key,value) pair and insert that into the built INodeContext.\r
+     * \r
+     * <p>\r
+     * This method works around the need to create NodeContextBuilder instances.\r
+     * </p>\r
+     * \r
+     * <p>\r
+     * Notice that your input object must properly implement <code>equals</code>\r
+     * and <code>hashCode</code> in order for GraphExplorer's automatic node\r
+     * expansion state tracking to work.\r
+     * </p>\r
+     * \r
+     * @param input\r
+     * @return an INodeContext containing the specified object as with the key\r
+     *         {@link BuiltinKeys#INPUT}\r
+     */\r
+    public static NodeContext buildWithInput(Object input) {\r
+        return new InputNodeContext(input);\r
+    }\r
+\r
+}\r