]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/NodeContextPath.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.browsing.ui / src / org / simantics / browsing / ui / NodeContextPath.java
diff --git a/bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/NodeContextPath.java b/bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/NodeContextPath.java
new file mode 100644 (file)
index 0000000..6b5fcbf
--- /dev/null
@@ -0,0 +1,257 @@
+/*******************************************************************************\r
+ * Copyright (c) 2005, 2007 IBM Corporation and others.\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
+ *     IBM Corporation - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.browsing.ui;\r
+\r
+import java.util.Arrays;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.core.runtime.IAdaptable;\r
+\r
+/**\r
+ * A {@link GraphExplorer} tree {@link NodeContext} path denotes a model element\r
+ * in a tree viewer. Tree path objects have value semantics. A model element is\r
+ * represented by a path of elements in the tree from the root element to the\r
+ * leaf element.\r
+ * <p>\r
+ * Clients may instantiate this class. Not intended to be subclassed.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * Directly imitated for the Simantics browsing framework from JFace\r
+ * <code>org.eclipse.jface.viewer.TreePath</code> class.\r
+ * </p>\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public final class NodeContextPath implements IAdaptable {\r
+\r
+    public static final NodeContextPath[] NONE  = {};\r
+\r
+    /**\r
+     * Constant for representing an empty tree path.\r
+     */\r
+    public static final NodeContextPath   EMPTY = new NodeContextPath(NodeContext.NONE);\r
+\r
+    private final NodeContext[]           segments;\r
+\r
+    private int                           hash;\r
+\r
+    /**\r
+     * Constructs a path identifying a leaf node in a tree.\r
+     * \r
+     * @param segments\r
+     *            path of elements to a leaf node in a tree, starting with the\r
+     *            root element\r
+     */\r
+    public NodeContextPath(NodeContext... segments) {\r
+        Assert.isNotNull(segments);\r
+        for (int i = 0; i < segments.length; i++) {\r
+            Assert.isNotNull(segments[i]);\r
+        }\r
+        this.segments = segments;\r
+    }\r
+\r
+    /**\r
+     * Returns the element at the specified index in this path.\r
+     * \r
+     * @param index\r
+     *            index of element to return\r
+     * @return element at the specified index\r
+     */\r
+    public NodeContext getSegment(int index) {\r
+        return segments[index];\r
+    }\r
+\r
+    /**\r
+     * Returns the number of elements in this path.\r
+     * \r
+     * @return the number of elements in this path\r
+     */\r
+    public int getSegmentCount() {\r
+        return segments.length;\r
+    }\r
+\r
+    /**\r
+     * Returns the first element in this path, or <code>null</code> if this\r
+     * path has no segments.\r
+     * \r
+     * @return the first element in this path\r
+     */\r
+    public NodeContext getFirstSegment() {\r
+        if (segments.length == 0) {\r
+            return null;\r
+        }\r
+        return segments[0];\r
+    }\r
+\r
+    /**\r
+     * Returns the last element in this path, or <code>null</code> if this\r
+     * path has no segments.\r
+     * \r
+     * @return the last element in this path\r
+     */\r
+    public NodeContext getLastSegment() {\r
+        if (segments.length == 0) {\r
+            return null;\r
+        }\r
+        return segments[segments.length - 1];\r
+    }\r
+\r
+    /**\r
+     * @return all the segments in the path as an array\r
+     */\r
+    public NodeContext[] getSegments() {\r
+        if (segments.length == 0)\r
+            return segments;\r
+        return Arrays.copyOf(segments, segments.length);\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.lang.Object#equals(java.lang.Object)\r
+     */\r
+    public boolean equals(Object other) {\r
+        if (!(other instanceof NodeContextPath)) {\r
+            return false;\r
+        }\r
+        return equals((NodeContextPath) other);\r
+    }\r
+\r
+    /**\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.lang.Object#hashCode()\r
+     */\r
+    public int hashCode() {\r
+        if (hash == 0) {\r
+            hash = hashCode0();\r
+        }\r
+        return hash;\r
+    }\r
+\r
+    /**\r
+     * Returns a hash code computed from the hash codes of the segments, using\r
+     * the given comparer to compute the hash codes of the segments.\r
+     * \r
+     * @param comparer\r
+     *            comparer to use or <code>null</code> if the segments' hash\r
+     *            codes should be computed by calling their hashCode() methods.\r
+     * @return the computed hash code\r
+     */\r
+    private int hashCode0() {\r
+        int result = 0;\r
+        for (int i = 0; i < segments.length; i++) {\r
+            result += segments[i].hashCode();\r
+        }\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * Returns whether this path is equivalent to the given path using the\r
+     * specified comparer to compare individual elements.\r
+     * \r
+     * @param otherPath\r
+     *            tree path to compare to\r
+     * @param comparer\r
+     *            comparator to use or <code>null</code> if segments should be\r
+     *            compared using equals()\r
+     * @return whether the paths are equal\r
+     */\r
+    public boolean equals(NodeContextPath otherPath) {\r
+        if (otherPath == null) {\r
+            return false;\r
+        }\r
+        if (segments.length != otherPath.segments.length) {\r
+            return false;\r
+        }\r
+        for (int i = 0; i < segments.length; i++) {\r
+            if (!segments[i].equals(otherPath.segments[i])) {\r
+                return false;\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Returns whether this path starts with the same segments as the given\r
+     * path, using the given comparer to compare segments.\r
+     * \r
+     * @param treePath\r
+     *            path to compare to\r
+     * @param comparer\r
+     *            the comparer to use, or <code>null</code> if equals() should\r
+     *            be used to compare segments\r
+     * @return whether the given path is a prefix of this path, or the same as\r
+     *         this path\r
+     */\r
+    public boolean startsWith(NodeContextPath treePath) {\r
+        int thisSegmentCount = getSegmentCount();\r
+        int otherSegmentCount = treePath.getSegmentCount();\r
+        if (otherSegmentCount == thisSegmentCount) {\r
+            return equals(treePath);\r
+        }\r
+        if (otherSegmentCount > thisSegmentCount) {\r
+            return false;\r
+        }\r
+        for (int i = 0; i < otherSegmentCount; i++) {\r
+            Object otherSegment = treePath.getSegment(i);\r
+            if (!otherSegment.equals(segments[i])) {\r
+                return false;\r
+            }\r
+        }\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Returns a copy of this tree path with one segment removed from the end,\r
+     * or <code>null</code> if this tree path has no segments.\r
+     * @return a tree path\r
+     */\r
+    public NodeContextPath getParentPath() {\r
+        int segmentCount = getSegmentCount();\r
+        if (segmentCount < 1) {\r
+            return null;\r
+        } else if (segmentCount == 1) {\r
+            return EMPTY;\r
+        }\r
+        NodeContext[] parentSegments = new NodeContext[segmentCount - 1];\r
+        System.arraycopy(segments, 0, parentSegments, 0, segmentCount - 1);\r
+        return new NodeContextPath(parentSegments);\r
+    }\r
+\r
+    /**\r
+     * Returns a copy of this tree path with the given segment added at the end.\r
+     * @param newSegment \r
+     * @return a tree path\r
+     */\r
+    public NodeContextPath createChildPath(NodeContext newSegment) {\r
+        int segmentCount = getSegmentCount();\r
+        NodeContext[] childSegments = new NodeContext[segmentCount + 1];\r
+        if(segmentCount>0) {\r
+            System.arraycopy(segments, 0, childSegments, 0, segmentCount);\r
+        }\r
+        childSegments[segmentCount] = newSegment;\r
+        return new NodeContextPath(childSegments);\r
+    }\r
+\r
+    @SuppressWarnings("rawtypes")\r
+    @Override\r
+    public Object getAdapter(Class adapter) {\r
+        if (NodeContext.class == adapter)\r
+            return getLastSegment();\r
+        NodeContext last = getLastSegment();\r
+        if (last instanceof IAdaptable)\r
+            return ((IAdaptable) last).getAdapter(adapter);\r
+        return null;\r
+    }\r
+\r
+}\r