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 2016/06/20 17:26:51 UTC

tinkerpop git commit: Added Lambda interface which can be used by Gremlin-Java and other strongly typed Gremlin variants. Lambda provides methods for function, predicate, supplier, comparator, etc. where the returned Lambda object has a getLambdaScript()

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1278 f5a28e804 -> 0cdb3cce0


Added Lambda interface which can be used by Gremlin-Java and other strongly typed Gremlin variants. Lambda provides methods for function, predicate, supplier, comparator, etc. where the returned Lambda object has a getLambdaScript() and can be introspected by a XXXTranslator accordingly. This solves the Lambda problem for Java/Scala/etc. While Groovy can use Lambda, it doesn't need to as it will assume all closures yield the lambda script string.


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

Branch: refs/heads/TINKERPOP-1278
Commit: 0cdb3cce0adaf150c6844395690de9b4a7184457
Parents: f5a28e8
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Jun 20 11:26:45 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Jun 20 11:26:45 2016 -0600

----------------------------------------------------------------------
 .../tinkerpop/gremlin/util/function/Lambda.java | 120 +++++++++++++++++++
 .../gremlin/groovy/GroovyTranslatorTest.java    |  59 ++++++---
 .../gremlin/groovy/GroovyTranslator.java        |  11 +-
 .../gremlin/python/PythonTranslator.java        |  11 +-
 .../gremlin/python/PythonBypassTranslator.java  |   4 +
 .../gremlin/python/PythonTranslatorTest.java    |  55 ++++++++-
 6 files changed, 225 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0cdb3cce/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/Lambda.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/Lambda.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/Lambda.java
new file mode 100644
index 0000000..cdb4239
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/Lambda.java
@@ -0,0 +1,120 @@
+/*
+ *  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.util.function;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public interface Lambda extends Serializable {
+
+    public String getLambdaScript();
+
+    public abstract static class AbstractLambda implements Lambda {
+        private final String lambdaSource;
+
+        private AbstractLambda(final String lambdaSource) {
+            this.lambdaSource = lambdaSource;
+        }
+
+        @Override
+        public String getLambdaScript() {
+            return this.lambdaSource;
+        }
+    }
+
+    public static class SimpleLambda<A, B> extends AbstractLambda implements Function<A, B>, Predicate<A>, Supplier<A>, Consumer<A>, Comparator<A> {
+        public SimpleLambda(final String lambdaSource) {
+            super(lambdaSource);
+        }
+
+        @Override
+        public B apply(final A a) {
+            return null;
+        }
+
+        @Override
+        public boolean test(final A a) {
+            return false;
+        }
+
+        @Override
+        public A get() {
+            return null;
+        }
+
+        @Override
+        public void accept(final A a) {
+
+        }
+
+        @Override
+        public int compare(final A first, final A second) {
+            return 0;
+        }
+    }
+
+    public static class ComplexLambda<A, B, C> extends AbstractLambda implements BiFunction<A, B, C> {
+
+        public ComplexLambda(final String lambdaSource) {
+            super(lambdaSource);
+        }
+
+        @Override
+        public C apply(final A a, final B b) {
+            return null;
+        }
+    }
+
+
+    ////
+
+    public static <A, B> Function<A, B> function(final String lambdaSource) {
+        return new SimpleLambda<>(lambdaSource);
+    }
+
+    public static <A> Predicate<A> predicate(final String lambdaSource) {
+        return new SimpleLambda<>(lambdaSource);
+    }
+
+    public static <A> Consumer<A> consumer(final String lambdaSource) {
+        return new SimpleLambda<>(lambdaSource);
+    }
+
+    public static <A> Supplier<A> supplier(final String lambdaSource) {
+        return new SimpleLambda<>(lambdaSource);
+    }
+
+    public static <A> Comparator<A> comparator(final String lambdaSource) {
+        return new SimpleLambda<>(lambdaSource);
+    }
+
+    public static <A, B, C> BiFunction<A, B, C> biFunction(final String lambdaSource) {
+        return new ComplexLambda<>(lambdaSource);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0cdb3cce/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslatorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslatorTest.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslatorTest.java
index d7ff1a0..c477257 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslatorTest.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslatorTest.java
@@ -21,15 +21,19 @@ package org.apache.tinkerpop.gremlin.groovy;
 
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -40,22 +44,45 @@ public class GroovyTranslatorTest extends AbstractGremlinTest {
     @LoadGraphWith(LoadGraphWith.GraphData.MODERN)
     public void shouldSupportStringSupplierLambdas() throws Exception {
         final GraphTraversalSource g = graph.traversal().withTranslator(GroovyTranslator.of("g"));
-        GraphTraversal.Admin<Vertex, Integer> t = (GraphTraversal.Admin) g.V().hasLabel("person").out().map(x -> "it.get().value('name').length()").asAdmin();
-        List<Integer> lengths = t.toList();
+        GraphTraversal.Admin<Vertex, Integer> t = g.withSideEffect("lengthSum", 0).withSack(1)
+                .V()
+                .filter(Lambda.predicate("it.get().label().equals('person')"))
+                .flatMap(Lambda.<Traverser<Vertex>, Iterator<Vertex>>function("it.get().vertices(Direction.OUT)"))
+                .map(Lambda.<Traverser<Vertex>, Integer>function("it.get().value('name').length()"))
+                .sideEffect(Lambda.consumer("{ x -> x.sideEffects(\"lengthSum\", x.<Integer>sideEffects('lengthSum') + x.get()) }"))
+                .order().by(Lambda.comparator("a,b -> a <=> b"))
+                .sack(Lambda.biFunction("{ a,b -> a + b }"))
+                .asAdmin();
+        final List<Integer> sacks = new ArrayList<>();
+        final List<Integer> lengths = new ArrayList<>();
+        while (t.hasNext()) {
+            final Traverser.Admin<Integer> traverser = t.getEndStep().next();
+            sacks.add(traverser.sack());
+            lengths.add(traverser.get());
+        }
+        assertFalse(t.hasNext());
+        //
         assertEquals(6, lengths.size());
-        assertTrue(lengths.contains(3));
-        assertTrue(lengths.contains(4));
-        assertTrue(lengths.contains(5));
-        assertTrue(lengths.contains(6));
-        assertEquals(24, g.V().hasLabel("person").out().map(x -> "it.get().value('name').length()").sum().next().intValue());
+        assertEquals(3, lengths.get(0).intValue());
+        assertEquals(3, lengths.get(1).intValue());
+        assertEquals(3, lengths.get(2).intValue());
+        assertEquals(4, lengths.get(3).intValue());
+        assertEquals(5, lengths.get(4).intValue());
+        assertEquals(6, lengths.get(5).intValue());
+        ///
+        assertEquals(6, sacks.size());
+        assertEquals(4, sacks.get(0).intValue());
+        assertEquals(4, sacks.get(1).intValue());
+        assertEquals(4, sacks.get(2).intValue());
+        assertEquals(5, sacks.get(3).intValue());
+        assertEquals(6, sacks.get(4).intValue());
+        assertEquals(7, sacks.get(5).intValue());
+        //
+        assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
+    }
 
-        /*t = g.V().hasLabel("person").out().filter(x -> "{ x.sideEffects('lengthSum', x.get().value('name').length()").asAdmin();
-        lengths = t.toList();
-        assertEquals(6, lengths.size());
-        assertTrue(lengths.contains(3));
-        assertTrue(lengths.contains(4));
-        assertTrue(lengths.contains(5));
-        assertTrue(lengths.contains(6));
-        assertEquals(24, g.V().hasLabel("person").out().map(x -> "it.get().value('name').length()").sum().next().intValue());*/
+    @Test
+    public void shouldHaveValidToString() {
+        assertEquals("translator[h:gremlin-java->gremlin-groovy]", GroovyTranslator.of("h").toString());
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0cdb3cce/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslator.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslator.java
index b17692e..8584067 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslator.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/GroovyTranslator.java
@@ -33,10 +33,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.TranslatorHelper;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.Function;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -147,12 +147,9 @@ public final class GroovyTranslator implements Translator {
             return convertToString(((Element) object).id()); // hack
         else if (object instanceof Computer) { // TODO: blow out
             return "";
-        } else if (object instanceof Function) {
-            try {
-                return "{" + ((Function) object).apply(null).toString() + "}";
-            } catch (final Exception e) {
-                return object.toString(); // TODO: hack for testing
-            }
+        } else if (object instanceof Lambda) {
+            final String lambdaString = ((Lambda) object).getLambdaScript();
+            return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
         } else if (object instanceof Traversal) {
             final TranslationStrategy strategy = (TranslationStrategy) ((Traversal.Admin) object).getStrategies().toList()
                     .stream()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0cdb3cce/gremlin-variant/src/main/java/org/apache/tinkerpop/gremlin/python/PythonTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-variant/src/main/java/org/apache/tinkerpop/gremlin/python/PythonTranslator.java b/gremlin-variant/src/main/java/org/apache/tinkerpop/gremlin/python/PythonTranslator.java
index 734396a..79eee72 100644
--- a/gremlin-variant/src/main/java/org/apache/tinkerpop/gremlin/python/PythonTranslator.java
+++ b/gremlin-variant/src/main/java/org/apache/tinkerpop/gremlin/python/PythonTranslator.java
@@ -36,6 +36,7 @@ import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
@@ -45,7 +46,6 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -187,12 +187,9 @@ public class PythonTranslator implements Translator {
             return strategy.getTranslator().getTraversalScript();
         } else if (object instanceof Computer) {
             return "";
-        } else if (object instanceof Function) {
-            try {
-                return "lambda: \"" + ((Function) object).apply(null).toString() + "\"";
-            } catch (final Exception e) {
-                return object.toString(); // TODO: hack for testing
-            }
+        } else if (object instanceof Lambda) {
+            final String lambdaString = ((Lambda) object).getLambdaScript();
+            return lambdaString.startsWith("lambda") ? "\"" + lambdaString + "\"" : "lambda: \"" + lambdaString + "\"";
         } else
             return null == object ? "" : object.toString();
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0cdb3cce/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonBypassTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonBypassTranslator.java b/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonBypassTranslator.java
index 8eb2d23..a3b11bc 100644
--- a/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonBypassTranslator.java
+++ b/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonBypassTranslator.java
@@ -39,6 +39,10 @@ class PythonBypassTranslator extends PythonTranslator {
         super(alias, importStatics);
     }
 
+    public static PythonBypassTranslator of(final String alias) {
+        return new PythonBypassTranslator(alias, false);
+    }
+
     public static PythonBypassTranslator of(final String alias, final boolean importStatics) {
         return new PythonBypassTranslator(alias, importStatics);
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0cdb3cce/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonTranslatorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonTranslatorTest.java b/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonTranslatorTest.java
index 6102dd8..27a43bd 100644
--- a/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonTranslatorTest.java
+++ b/gremlin-variant/src/test/java/org/apache/tinkerpop/gremlin/python/PythonTranslatorTest.java
@@ -19,14 +19,22 @@
 
 package org.apache.tinkerpop.gremlin.python;
 
-import org.apache.tinkerpop.gremlin.groovy.GroovyTranslator;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.creation.TranslationStrategy;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -38,10 +46,47 @@ public class PythonTranslatorTest {
 
     @Test
     public void shouldSupportStringSupplierLambdas() throws Exception {
-        final GraphTraversalSource g = TinkerFactory.createModern().traversal().withTranslator(GroovyTranslator.of("g"));
-        GraphTraversal.Admin<Vertex, Number> t = (GraphTraversal.Admin) g.V().hasLabel("person").out().map(x -> "it.get().value('name').length()").asAdmin();
-        System.out.println(t.getStrategies().getStrategy(TranslationStrategy.class).get().getTranslator().getTraversalScript());
-        System.out.print(t.toList());
+        final GraphTraversalSource g = TinkerFactory.createModern().traversal().withTranslator(PythonBypassTranslator.of("g",true));
+        GraphTraversal.Admin<Vertex, Integer> t = g.withSideEffect("lengthSum", 0).withSack(1)
+                .V()
+                .filter(Lambda.predicate("it.get().label().equals('person')"))
+                .flatMap(Lambda.<Traverser<Vertex>, Iterator<Vertex>>function("it.get().vertices(Direction.OUT)"))
+                .map(Lambda.<Traverser<Vertex>, Integer>function("it.get().value('name').length()"))
+                .sideEffect(Lambda.consumer("x -> x.sideEffects('lengthSum', x.<Integer>sideEffects('lengthSum') + x.get())"))
+                .order().by(Lambda.comparator("a,b -> a <=> b"))
+                .sack(Lambda.biFunction("a,b -> a + b"))
+                .asAdmin();
+        final List<Integer> sacks = new ArrayList<>();
+        final List<Integer> lengths = new ArrayList<>();
+        while (t.hasNext()) {
+            final Traverser.Admin<Integer> traverser = t.getEndStep().next();
+            sacks.add(traverser.sack());
+            lengths.add(traverser.get());
+        }
+        assertFalse(t.hasNext());
+        //
+        assertEquals(6, lengths.size());
+        assertEquals(3, lengths.get(0).intValue());
+        assertEquals(3, lengths.get(1).intValue());
+        assertEquals(3, lengths.get(2).intValue());
+        assertEquals(4, lengths.get(3).intValue());
+        assertEquals(5, lengths.get(4).intValue());
+        assertEquals(6, lengths.get(5).intValue());
+        ///
+        assertEquals(6, sacks.size());
+        assertEquals(4, sacks.get(0).intValue());
+        assertEquals(4, sacks.get(1).intValue());
+        assertEquals(4, sacks.get(2).intValue());
+        assertEquals(5, sacks.get(3).intValue());
+        assertEquals(6, sacks.get(4).intValue());
+        assertEquals(7, sacks.get(5).intValue());
+        //
+        assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
+    }
+
+    @Test
+    public void shouldHaveValidToString() {
+        assertEquals("translator[h:gremlin-java->jython]", PythonTranslator.of("h").toString());
     }
 
 }