You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/06/11 20:11:10 UTC

[4/4] incubator-tinkerpop git commit: Optimize ImmutablePath getSingle and getList

Optimize ImmutablePath getSingle and getList


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/5e9ad8d7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/5e9ad8d7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/5e9ad8d7

Branch: refs/heads/master
Commit: 5e9ad8d7dff6c63b9746147a1d255cbf7258cea3
Parents: 027d631
Author: mhfrantz <mf...@redsealnetworks.com>
Authored: Thu Jun 11 10:52:43 2015 -0700
Committer: mhfrantz <mf...@redsealnetworks.com>
Committed: Thu Jun 11 10:52:43 2015 -0700

----------------------------------------------------------------------
 .../traversal/step/util/ImmutablePath.java      | 67 ++++++++++++++++++--
 .../traversal/step/util/ImmutablePathImpl.java  | 58 +++++++++++++++++
 2 files changed, 120 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/5e9ad8d7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
index eb7e969..4195c5e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
@@ -32,9 +32,9 @@ import java.util.stream.Stream;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class ImmutablePath implements Path, Serializable, Cloneable {
+public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Cloneable {
 
-    private Path previousPath = HeadPath.instance();
+    private ImmutablePathImpl previousPath = HeadPath.instance();
     private Object currentObject;
     private Set<String> currentLabels = new LinkedHashSet<>();
 
@@ -56,7 +56,7 @@ public class ImmutablePath implements Path, Serializable, Cloneable {
         this(HeadPath.instance(), currentObject, currentLabels);
     }
 
-    private ImmutablePath(final Path previousPath, final Object currentObject, final Set<String> currentLabels) {
+    private ImmutablePath(final ImmutablePathImpl previousPath, final Object currentObject, final Set<String> currentLabels) {
         this.previousPath = previousPath;
         this.currentObject = currentObject;
         this.currentLabels.addAll(currentLabels);
@@ -78,6 +78,45 @@ public class ImmutablePath implements Path, Serializable, Cloneable {
     }
 
     @Override
+    public <A> List<A> getList(final String label) {
+        // Recursively build the list to avoid building objects/labels collections.
+        final List<A> list = this.previousPath.getList(label);
+        // Add our object, if our step labels match.
+        if (this.currentLabels.contains(label))
+            list.add((A)currentObject);
+        return list;
+    }
+
+    @Override
+    public <A> A getSingleHead(final String label) {
+        // Recursively search for the single value to avoid building throwaway collections, and to stop looking when we
+        // find it.
+        A single = this.previousPath.getSingleHead(label);
+        if (null == single) {
+            // See if we have a value.
+            if (this.currentLabels.contains(label)) {
+                single = (A) this.currentObject;
+            }
+        }
+        return single;
+    }
+
+    @Override
+    public <A> A getSingleTail(final String label) {
+        // Recursively search for the single value to avoid building throwaway collections, and to stop looking when we
+        // find it.
+        A single;
+        // See if we have a value.
+        if (this.currentLabels.contains(label)) {
+            single = (A) this.currentObject;
+        } else {
+            // Look for a previous value.
+            single = this.previousPath.getSingleTail(label);
+        }
+        return single;
+    }
+
+    @Override
     public boolean hasLabel(final String label) {
         return this.currentLabels.contains(label) || this.previousPath.hasLabel(label);
     }
@@ -108,7 +147,7 @@ public class ImmutablePath implements Path, Serializable, Cloneable {
         return this.objects().toString();
     }
 
-    private static class HeadPath implements Path {
+    private static class HeadPath implements Path, ImmutablePathImpl {
         private static final HeadPath INSTANCE = new HeadPath();
 
         private HeadPath() {
@@ -136,6 +175,24 @@ public class ImmutablePath implements Path, Serializable, Cloneable {
         }
 
         @Override
+        public <A> List<A> getList(final String label) {
+            // Provide an empty, modifiable list as a seed for ImmutablePath.getList.
+            return new ArrayList<A>();
+        }
+
+        @Override
+        public <A> A getSingleHead(final String label) {
+            // Provide a null to bounce the search back to ImmutablePath.getSingleHead.
+            return null;
+        }
+
+        @Override
+        public <A> A getSingleTail(final String label) {
+            // Provide a null to bounce the search back to ImmutablePath.getSingleTail.
+            return null;
+        }
+
+        @Override
         public boolean hasLabel(final String label) {
             return false;
         }
@@ -165,7 +222,7 @@ public class ImmutablePath implements Path, Serializable, Cloneable {
             return this;
         }
 
-        public static Path instance() {
+        public static HeadPath instance() {
             return INSTANCE;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/5e9ad8d7/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePathImpl.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePathImpl.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePathImpl.java
new file mode 100644
index 0000000..74be069
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePathImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+
+/**
+ * Internal interface used by ImmutablePath to provide more efficient implementation.
+ *
+ * @author Matt Frantz (http://github.com/mhfrantz)
+ */
+interface ImmutablePathImpl extends Path {
+
+    @Override
+    public default <A> A getSingle(final Pop pop, final String label) {
+        // Delegate to the non-throwing, optimized head/tail calculations.
+        final A single = Pop.tail == pop ? this.getSingleTail(label) : this.getSingleHead(label);
+        // Throw if we didn't find the label.
+        if (null == single)
+            throw Path.Exceptions.stepWithProvidedLabelDoesNotExist(label);
+        return single;
+    }
+
+    /**
+     * Get the object least recently associated with the particular label of the path.
+     *
+     * @param label the label of the path
+     * @param <A>   the type of the object associated with the label
+     * @return the object associated with the label of the path or null if the path does not contain the label
+     */
+    public <A> A getSingleHead(String label);
+
+    /**
+     * Get the object most recently associated with the particular label of the path.
+     *
+     * @param label the label of the path
+     * @param <A>   the type of the object associated with the label
+     * @return the object associated with the label of the path or null if the path does not contain the label
+     */
+    public <A> A getSingleTail(String label);
+}