Repository: tinkerpop Updated Branches: refs/heads/master edf1ddcbc -> b4c64fc61
Initial commit for sparql-gremlin changes Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ff3a2e02 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ff3a2e02 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ff3a2e02 Branch: refs/heads/master Commit: ff3a2e02fc0fb374a8db192f78e6e94d5e192b22 Parents: edf1ddc Author: harsh9t <hars...@gmail.com> Authored: Thu Jan 18 01:33:29 2018 +0100 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Mon Aug 13 14:38:19 2018 -0400 ---------------------------------------------------------------------- sparql-gremlin/pom.xml | 63 +++ .../gremlin/sparql/ConsoleCompiler.java | 165 ++++++++ .../tinkerpop/gremlin/sparql/Prefixes.java | 64 ++++ .../gremlin/sparql/SparqlToGremlinCompiler.java | 381 +++++++++++++++++++ .../gremlin/sparql/TraversalBuilder.java | 82 ++++ .../gremlin/sparql/WhereTraversalBuilder.java | 134 +++++++ .../tinkerpop/gremlin/sparql/PrefixesTest.java | 67 ++++ .../gremlin/sparql/ResourceHelper.java | 37 ++ .../sparql/SparqlToGremlinCompilerTest.java | 223 +++++++++++ 9 files changed, 1216 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/pom.xml ---------------------------------------------------------------------- diff --git a/sparql-gremlin/pom.xml b/sparql-gremlin/pom.xml new file mode 100644 index 0000000..e134d31 --- /dev/null +++ b/sparql-gremlin/pom.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>tinkerpop</artifactId> + <groupId>org.apache.tinkerpop</groupId> + <version>3.3.2-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>sparql-gremlin</artifactId> + <organization> + <name>WDAQUA-ITN</name> + <url>http://wdaqua.eu</url> + </organization> + <developers> + <developer> + <name>Harsh Thakkar</name> + <email>hars...@gmail.com</email> + <organization>University of Bonn</organization> + <organizationUrl>http://harshthakkar.in</organizationUrl> + </developer> + <developer> + <name>Dharmen Punjani</name> + <email>dharmen.punj...@gmail.com</email> + <organization>National and Kapodistrian University of Athens</organization> + <organizationUrl>http://wdaqua.eu/students/dharmen-punjani</organizationUrl> + </developer> + </developers> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <jena.version>3.0.0</jena.version> + <query.dir>src/test/resources/sparql/queries</query.dir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>apache-jena-libs</artifactId> + <type>pom</type> + <version>${jena.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-core</artifactId> + <version>3.3.2-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>tinkergraph-gremlin</artifactId> + <version>3.3.2-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/ConsoleCompiler.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/ConsoleCompiler.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/ConsoleCompiler.java new file mode 100644 index 0000000..0d50475 --- /dev/null +++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/ConsoleCompiler.java @@ -0,0 +1,165 @@ +/* + * 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.sparql; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator; +import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.io.IoCore; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; + +import org.apache.tinkerpop.gremlin.sparql.SparqlToGremlinCompiler; + +class ConsoleCompiler { + + public static void main(final String[] args) throws IOException { + //args = "/examples/modern1.sparql"; + final Options options = new Options(); + options.addOption("f", "file", true, "a file that contains a SPARQL query"); + options.addOption("g", "graph", true, "the graph that's used to execute the query [classic|modern|crew|kryo file]"); + // TODO: add an OLAP option (perhaps: "--olap spark"?) + + final CommandLineParser parser = new DefaultParser(); + final CommandLine commandLine; + + try { + commandLine = parser.parse(options, args); + } catch (ParseException e) { + System.out.println(e.getMessage()); + printHelp(1); + return; + } + + final InputStream inputStream = commandLine.hasOption("file") + ? new FileInputStream(commandLine.getOptionValue("file")) + : System.in; + final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + final StringBuilder queryBuilder = new StringBuilder(); + + if (!reader.ready()) { + printHelp(1); + } + + String line; + while (null != (line = reader.readLine())) { + queryBuilder.append(System.lineSeparator()).append(line); + } + + final String queryString = queryBuilder.toString(); + Graph graph; + + if (commandLine.hasOption("graph")) { + switch (commandLine.getOptionValue("graph").toLowerCase()) { + case "classic": + graph = TinkerFactory.createClassic(); + break; + case "modern": + graph = TinkerFactory.createModern(); + System.out.println("Modern Graph Created"); + break; + case "crew": + graph = TinkerFactory.createTheCrew(); + break; + default: + graph = TinkerGraph.open(); + System.out.println("Graph Created"); + String graphName = commandLine.getOptionValue("graph"); + long startTime= System.currentTimeMillis(); + if(graphName.endsWith(".graphml")) + graph.io(IoCore.graphml()).readGraph(graphName); + else if(graphName.endsWith(".kryo")||graphName.endsWith("gryo")) + graph.io(IoCore.gryo()).readGraph(graphName); + long endTime = System.currentTimeMillis(); + System.out.println("Time taken to load graph from kyro file: "+ (endTime-startTime)+" mili seconds"); + break; + } + } else { + + graph = TinkerFactory.createModern(); + } + + long startTime = System.currentTimeMillis(); + final Traversal<Vertex, ?> traversal = SparqlToGremlinCompiler.convertToGremlinTraversal(graph, queryString); + long endTime = System.currentTimeMillis(); + System.out.println("Time traken to convert SPARQL to Gremlin Traversal : "+ (endTime - startTime)+ " miliseconds"); + + printWithHeadline("SPARQL Query", queryString); + // printWithHeadline("Traversal (prior execution)", traversal); + + + Bytecode traversalByteCode = traversal.asAdmin().getBytecode(); + + +// JavaTranslator.of(graph.traversal()).translate(traversalByteCode); +// +// System.out.println("the Byte Code : "+ traversalByteCode.toString()); + printWithHeadline("Result", String.join(System.lineSeparator(),JavaTranslator.of(graph.traversal()).translate(traversalByteCode).toStream().map(Object::toString).collect(Collectors.toList()))); + // printWithHeadline("Traversal (after execution)", traversal); + } + + private static void printHelp(final int exitCode) throws IOException { + final Map<String, String> env = System.getenv(); + final String command = env.containsKey("LAST_COMMAND") ? env.get("LAST_COMMAND") : "sparql-gremlin.sh"; + printWithHeadline("Usage Examples", String.join("\n", + command + " -f examples/modern1.sparql", + command + " < examples/modern2.sparql", + command + " <<< 'SELECT * WHERE { ?a e:knows ?b }'", + command + " -g crew < examples/crew1.sparql")); + if (exitCode >= 0) { + System.exit(exitCode); + } + } + + private static void printWithHeadline(final String headline, final Object content) throws IOException { + final StringReader sr = new StringReader(content != null ? content.toString() : "null"); + final BufferedReader br = new BufferedReader(sr); + String line; + System.out.println(); + System.out.println( headline ); + System.out.println(); + boolean skip = true; + while (null != (line = br.readLine())) { + skip &= line.isEmpty(); + if (!skip) { + System.out.println(" " + line); + } + } + System.out.println(); + br.close(); + sr.close(); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/Prefixes.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/Prefixes.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/Prefixes.java new file mode 100644 index 0000000..452bf68 --- /dev/null +++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/Prefixes.java @@ -0,0 +1,64 @@ +/* + * 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.sparql; + +import java.util.Arrays; +import java.util.List; + + +public class Prefixes { + + // public final static String BASE_URI = "http://northwind.com/model/"; + public final static String BASE_URI = "http://www.tinkerpop.com/traversal/"; + + final static List<String> PREFIXES = Arrays.asList("edge", "property", "value"); + + final static String PREFIX_DEFINITIONS; + + static { + final StringBuilder builder = new StringBuilder(); + for (final String prefix : PREFIXES) { + builder.append("PREFIX ").append(prefix.substring(0, 1)).append(": <").append(getURI(prefix)). + append(">").append(System.lineSeparator()); + } + PREFIX_DEFINITIONS = builder.toString(); + } + + public static String getURI(final String prefix) { + return BASE_URI + prefix + "#"; + } + + public static String getURIValue(final String uri) { + return uri.substring(uri.indexOf("#") + 1); + } + + public static String getPrefix(final String uri) { + final String tmp = uri.substring(0, uri.indexOf("#")); + return tmp.substring(tmp.lastIndexOf("/") + 1); + } + + public static String prepend(final String script) { + return PREFIX_DEFINITIONS + script; + } + + public static StringBuilder prepend(final StringBuilder scriptBuilder) { + return scriptBuilder.insert(0, PREFIX_DEFINITIONS); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java new file mode 100644 index 0000000..adb36e9 --- /dev/null +++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompiler.java @@ -0,0 +1,381 @@ +/* + * 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.sparql; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.jena.graph.Triple; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.SortCondition; +import org.apache.jena.query.Syntax; +import org.apache.jena.sparql.algebra.Algebra; +import org.apache.jena.sparql.algebra.Op; +import org.apache.jena.sparql.algebra.OpVisitorBase; +import org.apache.jena.sparql.algebra.OpWalker; +import org.apache.jena.sparql.algebra.op.OpBGP; +import org.apache.jena.sparql.algebra.op.OpFilter; +import org.apache.jena.sparql.algebra.op.OpLeftJoin; +import org.apache.jena.sparql.algebra.op.OpUnion; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.core.VarExprList; +import org.apache.jena.sparql.expr.Expr; +import org.apache.jena.sparql.expr.ExprAggregator; +import org.apache.tinkerpop.gremlin.process.traversal.Order; +import org.apache.tinkerpop.gremlin.process.traversal.Scope; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +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.dsl.graph.__; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; + +// TODO: implement OpVisitor, don't extend OpVisitorBase +public class SparqlToGremlinCompiler extends OpVisitorBase { + + private GraphTraversal<Vertex, ?> traversal; + + List<Traversal> traversalList = new ArrayList<Traversal>(); + + String groupVariable = ""; + int sortingDirection = 0; + long offsetLimit = 0; + String sortingVariable = ""; + + GraphTraversalSource temp; + Graph graph; + + private SparqlToGremlinCompiler(final GraphTraversal<Vertex, ?> traversal) { + this.traversal = traversal; + } + + private SparqlToGremlinCompiler(final GraphTraversalSource g) { + this(g.V()); + temp = g; + + } + + private SparqlToGremlinCompiler(final Graph g) { + this.traversal = (GraphTraversal<Vertex, ?>) g.traversal(); + graph = g; + } + + public String createMatchStep(String step) { + String st = ""; + step = step.substring(1, step.length() - 2); + String first = step.substring(0, step.indexOf(",")); + String second = step.substring(step.indexOf(",") + 1); + //System.out.println("First : " + first); + //System.out.println("Second : " + second); + st = first.substring(first.indexOf("["), first.length() - 1); + st = "[" + st + "," + second + "]"; + return st; + } + + GraphTraversal<Vertex, ?> convertToGremlinTraversal(final Query query) { + + // long startTime = System.currentTimeMillis(); + // long endTime; + final Op op = Algebra.compile(query); // SPARQL query compiles here to + // OP +// System.out.println("OP Tree: " + op.toString()); + + + OpWalker.walk(op, this); // OP is being walked here + + + + + //System.out.println("time taken for opWalker:"+ (endTime-startTime)); + // startTime = System.currentTimeMillis(); + int traversalIndex = 0; + int numberOfTraversal = traversalList.size(); + Traversal arrayOfAllTraversals[] = new Traversal[numberOfTraversal]; + + if (query.hasOrderBy() && !query.hasGroupBy()) { + List<SortCondition> sortingConditions = query.getOrderBy(); + int directionOfSort = 0; + + for (SortCondition sortCondition : sortingConditions) { + Expr expr = sortCondition.getExpression(); + directionOfSort = sortCondition.getDirection(); + sortingVariable = expr.getVarName(); + + } + + Order orderDirection = Order.incr; + if (directionOfSort == -1) { + orderDirection = Order.decr; + } + } + for (Traversal tempTrav : traversalList) { + + arrayOfAllTraversals[traversalIndex++] = tempTrav; + } + + int directionOfSort = 0; + Order orderDirection = Order.incr; + if (query.hasOrderBy()) { + List<SortCondition> sortingConditions = query.getOrderBy(); + + // + for (SortCondition sortCondition : sortingConditions) { + Expr expr = sortCondition.getExpression(); + directionOfSort = sortCondition.getDirection(); + sortingVariable = expr.getVarName(); +// System.out.println("order by var: "+sortingDirection); + } + // + + if (directionOfSort == -1) { + orderDirection = Order.decr; + } + + } + + if (traversalList.size() > 0) + traversal = traversal.match(arrayOfAllTraversals); + + final List<String> vars = query.getResultVars(); + List<ExprAggregator> lstexpr = query.getAggregators(); + if (!query.isQueryResultStar() && !query.hasGroupBy()) { + + switch (vars.size()) { + case 0: + throw new IllegalStateException(); + case 1: + if (query.isDistinct()) { +// System.out.println("Inside ------------------- >Select 1------------------------> Distinct"); + traversal = traversal.dedup(vars.get(0)); + } + if (query.hasOrderBy()) { +// System.out.println("Inside ------------------- >Select 1"); + traversal = traversal.order().by(sortingVariable, orderDirection); + } else { + + traversal = traversal.select(vars.get(0)); + } + break; + case 2: + if (query.isDistinct()) { + traversal = traversal.dedup(vars.get(0), vars.get(1)); + } + if (query.hasOrderBy()) { +// System.out.println("Inside ------------------- >Select 1"); + traversal = traversal.order().by(__.select(vars.get(0)), orderDirection).by(__.select(vars.get(1))); + } else + traversal = traversal.select(vars.get(0), vars.get(1)); + break; + default: + final String[] all = new String[vars.size()]; + vars.toArray(all); + if (query.isDistinct()) { + + traversal = traversal.dedup(all); + } + final String[] others = Arrays.copyOfRange(all, 2, vars.size()); + if (query.hasOrderBy()) { + + traversal = traversal.order().by(__.select(vars.get(0)), orderDirection).by(__.select(vars.get(1))); + + } else + traversal = traversal.select(vars.get(0), vars.get(1), others); + + break; + } + + } + + + if (query.hasGroupBy()) { + VarExprList lstExpr = query.getGroupBy(); + String grpVar = ""; + Traversal tempTrav; + for (Var expr : lstExpr.getVars()) { + grpVar = expr.getName(); + // System.out.println("The Group by var: " + expr.getName()); + } + + if (query.hasLimit()) { + long limit = query.getLimit(), offset = 0; + + if (query.hasOffset()) { + offset = query.getOffset(); + + } + // if (query.hasGroupBy() && query.hasOrderBy()) + // traversal = traversal.range( offset, offset + limit); + // else + // traversal = traversal.range(offset, offset + limit); + + } + + if (!grpVar.isEmpty()) + traversal = traversal.select(grpVar); + if (query.hasAggregators()) { + List<ExprAggregator> exprAgg = query.getAggregators(); + for (ExprAggregator expr : exprAgg) { + +// System.out.println("The Aggregator by var: " + expr.getAggregator().getExprList().toString() +// + " is :" + expr.getAggregator().toString()); + if (expr.getAggregator().getName().contains("COUNT")) { + if (!query.toString().contains("GROUP")) { + if (expr.getAggregator().toString().contains("DISTINCT")) { + traversal = traversal + .dedup(expr.getAggregator().getExprList().get(0).toString().substring(1)); + } else { + traversal = traversal + .select(expr.getAggregator().getExprList().get(0).toString().substring(1)); + } + traversal = traversal.count(); + } else + traversal = traversal.groupCount(); + } + if (expr.getAggregator().getName().contains("MAX")) { + traversal = traversal.max(); + } + } + + } else { + + traversal = traversal.group(); + } + + + } + + + if (query.hasOrderBy() && query.hasGroupBy()) { + + traversal = traversal.order().by(sortingVariable, orderDirection); + } + if (query.hasLimit()) { + long limit = query.getLimit(), offset = 0; + + if (query.hasOffset()) { + offset = query.getOffset(); + + } + if (query.hasGroupBy() && query.hasOrderBy()) + traversal = traversal.range(Scope.local, offset, offset + limit); + else + traversal = traversal.range(offset, offset + limit); + + } + // endTime = System.currentTimeMillis(); + // System.out.println("time taken for convertToGremlinTraversal Function : "+ (endTime-startTime)+" mili seconds"); + + return traversal; + } + + private static GraphTraversal<Vertex, ?> convertToGremlinTraversal(final GraphTraversalSource g, + final Query query) { + return new SparqlToGremlinCompiler(g).convertToGremlinTraversal(query); + } + + public static GraphTraversal<Vertex, ?> convertToGremlinTraversal(final Graph graph, final String query) { + return convertToGremlinTraversal(graph.traversal(), QueryFactory.create(Prefixes.prepend(query))); + } + + public static GraphTraversal<Vertex, ?> convertToGremlinTraversal(final GraphTraversalSource g, + final String query) { + return convertToGremlinTraversal(g, QueryFactory.create(Prefixes.prepend(query), Syntax.syntaxSPARQL)); + } + + // VISITING SPARQL ALGEBRA OP BASIC TRIPLE PATTERNS - MAYBE + @Override + public void visit(final OpBGP opBGP) { + { + + // System.out.println("Inside opBGP ---------------------------------------------->"); + final List<Triple> triples = opBGP.getPattern().getList(); + final Traversal[] matchTraversals = new Traversal[triples.size()]; + int i = 0; + for (final Triple triple : triples) { + + matchTraversals[i++] = TraversalBuilder.transform(triple); + traversalList.add(matchTraversals[i - 1]); + } + + } + + } + + // VISITING SPARQL ALGEBRA OP FILTER - MAYBE + @Override + public void visit(final OpFilter opFilter) { + + // System.out.println("Inside opFilter ---------------------------------------------->"); + Traversal traversal = null; + + for (Expr expr : opFilter.getExprs().getList()) { + if (expr != null) { + + traversal = __.where(WhereTraversalBuilder.transform(expr)); + traversalList.add(traversal); + } + } + + } + // TODO: add more functions for operators other than FILTER, such as + // OPTIONAL + // This can be done by understanding how Jena handles these other + // operators/filters inherently and then map them to Gremlin + + public void visit(final OpLeftJoin opLeftJoin) { + +// System.out.println("Inside opOptional ---------------------------------------------->"); +// System.out.println(opLeftJoin.getRight().toString()); + + } + + @Override + public void visit(final OpUnion opUnion) { + + // System.out.println("Inside opUnion ---------------------------------------------->"); + Traversal unionTemp[] = new Traversal[2]; + Traversal unionTemp1[] = new Traversal[traversalList.size() / 2]; + Traversal unionTemp2[] = new Traversal[traversalList.size() / 2]; + + int count = 0; + + for (int i = 0; i < traversalList.size(); i++) { + + if (i < traversalList.size() / 2) { + + unionTemp1[i] = traversalList.get(i); + } else { + unionTemp2[count++] = traversalList.get(i); + } + } + + unionTemp[1] = __.match(unionTemp2); + unionTemp[0] = __.match(unionTemp1); + + traversalList.clear(); + traversal = (GraphTraversal<Vertex, ?>) traversal.union(unionTemp); + // System.out.println("Getting out from Union -------------------> : + // "+traversal); + // traversalList.add(__.union(unionTemp)); + // traversalList.clear(); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/TraversalBuilder.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/TraversalBuilder.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/TraversalBuilder.java new file mode 100644 index 0000000..72a32a5 --- /dev/null +++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/TraversalBuilder.java @@ -0,0 +1,82 @@ +/* + * 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.sparql; + +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.structure.PropertyType; +import org.apache.tinkerpop.gremlin.structure.Vertex; + + +class TraversalBuilder { + + public static GraphTraversal<?, ?> transform(final Triple triple) { + final GraphTraversal<Vertex, ?> matchTraversal = __.as(triple.getSubject().getName()); + + final Node predicate = triple.getPredicate(); + final String uri = predicate.getURI(); + final String uriValue = Prefixes.getURIValue(uri); + final String prefix = Prefixes.getPrefix(uri); + + switch (prefix) { + case "edge": + return matchTraversal.out(uriValue).as(triple.getObject().getName()); + case "property": + return matchProperty(matchTraversal, uriValue, PropertyType.PROPERTY, triple.getObject()); + case "value": + return matchProperty(matchTraversal, uriValue, PropertyType.VALUE, triple.getObject()); + default: + throw new IllegalStateException(String.format("Unexpected predicate: %s", predicate)); + } + } + + private static GraphTraversal<?, ?> matchProperty(final GraphTraversal<?, ?> traversal, final String propertyName, + final PropertyType type, final Node object) { + switch (propertyName) { + case "id": + + return object.isConcrete() + ? traversal.hasId(object.getLiteralValue()) + : traversal.id().as(object.getName()); + case "label": + return object.isConcrete() + ? traversal.hasLabel(object.getLiteralValue().toString()) + : traversal.label().as(object.getName()); + case "key": + return object.isConcrete() + ? traversal.hasKey(object.getLiteralValue().toString()) + : traversal.key().as(object.getName()); + case "value": + return object.isConcrete() + ? traversal.hasValue(object.getLiteralValue().toString()) + : traversal.value().as(object.getName()); + default: + if (type.equals(PropertyType.PROPERTY)) { + return traversal.properties(propertyName).as(object.getName()); + } else { + return object.isConcrete() + ? traversal.values(propertyName).is(object.getLiteralValue()) + : traversal.values(propertyName).as(object.getName()); + } + } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/WhereTraversalBuilder.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/WhereTraversalBuilder.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/WhereTraversalBuilder.java new file mode 100644 index 0000000..f4d49b6 --- /dev/null +++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/WhereTraversalBuilder.java @@ -0,0 +1,134 @@ +/* + * 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.sparql; + +import java.util.List; + +import org.apache.jena.graph.Triple; +import org.apache.jena.sparql.algebra.op.OpBGP; +import org.apache.jena.sparql.expr.E_Equals; +import org.apache.jena.sparql.expr.E_Exists; +import org.apache.jena.sparql.expr.E_GreaterThan; +import org.apache.jena.sparql.expr.E_GreaterThanOrEqual; +import org.apache.jena.sparql.expr.E_LessThan; +import org.apache.jena.sparql.expr.E_LessThanOrEqual; +import org.apache.jena.sparql.expr.E_LogicalAnd; +import org.apache.jena.sparql.expr.E_LogicalOr; +import org.apache.jena.sparql.expr.E_NotEquals; +import org.apache.jena.sparql.expr.E_NotExists; +import org.apache.jena.sparql.expr.E_StrLength; +import org.apache.jena.sparql.expr.Expr; +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.Step; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; + +class WhereTraversalBuilder { + + public static GraphTraversal<?, ?> transform(final E_Equals expression) { + // System.out.println("The aggr one : "+expression.getArg1().getClass().getName() + "The aggr one :"+expression.getArg2().getClass().getName()); + final Object value = expression.getArg2().getConstant().getNode().getLiteralValue(); + return __.as(expression.getArg1().getVarName()).is(P.eq(value)); + } + + public static GraphTraversal<?, ?> transform(final E_NotEquals expression) { + final Object value = expression.getArg2().getConstant().getNode().getLiteralValue(); + return __.as(expression.getArg1().getVarName()).is(P.neq(value)); + } + + public static GraphTraversal<?, ?> transform(final E_LessThan expression) { + // System.out.println("The aggr one : "+expression.getArg1().getClass().getName() + "The aggr one :"+expression.getArg2().getClass().getName()); + final Object value = expression.getArg2().getConstant().getNode().getLiteralValue(); + return __.as(expression.getArg1().getVarName()).is(P.lt(value)); + } + + public static GraphTraversal<?, ?> transform(final E_LessThanOrEqual expression) { + // System.out.println("The aggr one : "+expression.getArg1().getClass().getName() + "The aggr one :"+expression.getArg2().getClass().getName()); + final Object value = expression.getArg2().getConstant().getNode().getLiteralValue(); + return __.as(expression.getArg1().getVarName()).is(P.lte(value)); + } + + public static GraphTraversal<?, ?> transform(final E_GreaterThan expression) { + final Object value = expression.getArg2().getConstant().getNode().getLiteralValue(); + return __.as(expression.getArg1().getVarName()).is(P.gt(value)); + } + + public static GraphTraversal<?, ?> transform(final E_GreaterThanOrEqual expression) { + final Object value = expression.getArg2().getConstant().getNode().getLiteralValue(); + return __.as(expression.getArg1().getVarName()).is(P.gte(value)); + } + + public static GraphTraversal<?, ?> transform(final E_LogicalAnd expression) { + return __.and( + transform(expression.getArg1()), + transform(expression.getArg2())); + } + + public static GraphTraversal<?, ?> transform(final E_LogicalOr expression) { + return __.or( + transform(expression.getArg1()), + transform(expression.getArg2())); + } + + public static GraphTraversal<?, ?> transform(final E_Exists expression) { + final OpBGP opBGP = (OpBGP) expression.getGraphPattern(); + final List<Triple> triples = opBGP.getPattern().getList(); + if (triples.size() != 1) throw new IllegalStateException("Unhandled EXISTS pattern"); + final GraphTraversal<?, ?> traversal = TraversalBuilder.transform(triples.get(0)); + final Step endStep = traversal.asAdmin().getEndStep(); + final String label = (String) endStep.getLabels().iterator().next(); + endStep.removeLabel(label); + return traversal; + } + + + public static GraphTraversal<?, ?> transform(final E_NotExists expression) { + final OpBGP opBGP = (OpBGP) expression.getGraphPattern(); + final List<Triple> triples = opBGP.getPattern().getList(); + if (triples.size() != 1) throw new IllegalStateException("Unhandled NOT EXISTS pattern"); + final GraphTraversal<?, ?> traversal = TraversalBuilder.transform(triples.get(0)); + final Step endStep = traversal.asAdmin().getEndStep(); + final String label = (String) endStep.getLabels().iterator().next(); + endStep.removeLabel(label); + return __.not(traversal); + } + + public static int getStrLength(final E_StrLength expression){ + + return expression.getArg().toString().length(); + + } + + + //what does <?, ?> signify? possibly <S,E> + public static GraphTraversal<?, ?> transform(final Expr expression) { + if (expression instanceof E_Equals) return transform((E_Equals) expression); + if (expression instanceof E_NotEquals) return transform((E_NotEquals) expression); + if (expression instanceof E_LessThan) return transform((E_LessThan) expression); + if (expression instanceof E_LessThanOrEqual) return transform((E_LessThanOrEqual) expression); + if (expression instanceof E_GreaterThan) return transform((E_GreaterThan) expression); + if (expression instanceof E_GreaterThanOrEqual) return transform((E_GreaterThanOrEqual) expression); + if (expression instanceof E_LogicalAnd) return transform((E_LogicalAnd) expression); + if (expression instanceof E_LogicalOr) return transform((E_LogicalOr) expression); + if (expression instanceof E_Exists) return transform((E_Exists) expression); + if (expression instanceof E_NotExists) return transform((E_NotExists) expression); + throw new IllegalStateException(String.format("Unhandled expression: %s", expression)); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/PrefixesTest.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/PrefixesTest.java b/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/PrefixesTest.java new file mode 100644 index 0000000..155680b --- /dev/null +++ b/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/PrefixesTest.java @@ -0,0 +1,67 @@ +/* + * 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.sparql; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PrefixesTest { + + final static String TEST_QUERY = String.join(System.lineSeparator(), "SELECT *", "WHERE {}"); + final static String PREFIXED_QUERY = String.join(System.lineSeparator(), + "PREFIX e: <" + Prefixes.BASE_URI + "edge#>", + "PREFIX p: <" + Prefixes.BASE_URI + "property#>", + "PREFIX v: <" + Prefixes.BASE_URI + "value#>", + TEST_QUERY); + + @Test + public void testGetURI() throws Exception { + final String prefix = "test"; + final String uri = Prefixes.BASE_URI + prefix + "#"; + assertEquals(uri, Prefixes.getURI(prefix)); + } + + @Test + public void testGetURIValue() throws Exception { + final String prefix = "test"; + final String value = "value"; + final String uri = Prefixes.getURI(prefix) + value; + assertEquals(value, Prefixes.getURIValue(uri)); + } + + @Test + public void testGetPrefix() throws Exception { + final String prefix = "test"; + final String uri = Prefixes.getURI(prefix); + assertEquals(prefix, Prefixes.getPrefix(uri)); + } + + @Test + public void testPrependString() throws Exception { + assertEquals(PREFIXED_QUERY, Prefixes.prepend(TEST_QUERY)); + } + + @Test + public void testPrependStringBuilder() throws Exception { + final StringBuilder builder = new StringBuilder(TEST_QUERY); + assertEquals(PREFIXED_QUERY, Prefixes.prepend(builder).toString()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/ResourceHelper.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/ResourceHelper.java b/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/ResourceHelper.java new file mode 100644 index 0000000..4f58e61 --- /dev/null +++ b/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/ResourceHelper.java @@ -0,0 +1,37 @@ +/* + * 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.sparql; + +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Daniel Kuppitz (http://gremlin.guru) + */ +public class ResourceHelper { + + public static String loadQuery(final String prefix, final int number) throws IOException { + final String path = "/queries/" + prefix + number + ".sparql"; + final InputStream stream = ResourceHelper.class.getResourceAsStream(path); + return IOUtils.toString(stream, "UTF-8"); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff3a2e02/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompilerTest.java ---------------------------------------------------------------------- diff --git a/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompilerTest.java b/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompilerTest.java new file mode 100644 index 0000000..3fb49e8 --- /dev/null +++ b/sparql-gremlin/src/test/java/org/apache/tinkerpop/gremlin/sparql/SparqlToGremlinCompilerTest.java @@ -0,0 +1,223 @@ +/* + * 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.sparql; + +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +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.Graph; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.apache.tinkerpop.gremlin.process.computer.Computer; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import static org.apache.tinkerpop.gremlin.sparql.SparqlToGremlinCompiler.convertToGremlinTraversal; +import static org.junit.Assert.assertEquals; + + +import java.io.IOException; + +import static org.apache.tinkerpop.gremlin.sparql.ResourceHelper.loadQuery; + + +public class SparqlToGremlinCompilerTest { + + private Graph modern, crew; + private GraphTraversalSource mg, cg; + private GraphTraversalSource mc, cc; +/* + @Before + public void setUp() throws Exception { + modern = TinkerFactory.createModern(); + mg = modern.traversal(); + mc = modern.traversal(computer()); + crew = TinkerFactory.createTheCrew(); + cg = modern.traversal(); + cc = modern.traversal(computer()); + } + + @Ignore + @Test + public void play() throws IOException { + final String query = loadQuery("modern", 11); + final Traversal traversal = convertToGremlinTraversal(modern, query); + System.out.println(traversal); + System.out.println(traversal.toList()); + System.out.println(traversal); + } + + /* Modern */ + + /* @Test + public void testModern1() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").hasLabel("person"), + as("a").out("knows").as("b"), + as("a").out("created").as("c"), + as("b").out("created").as("c"), + as("a").values("age").as("d")).where(as("d").is(lt(30))). + select("a", "b", "c"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 1))); + } + + @Test + public void testModern2() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").hasLabel("person"), + as("a").out("knows").as("b"), + as("a").out("created").as("c"), + as("b").out("created").as("c"), + as("a").values("age").as("d")).where(as("d").is(lt(30))); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 2))); + } + + @Test + public void testModern3() throws Exception { + final GraphTraversal expected = mg.V().match( + as("person").values("name").as("name"), + as("person").values("age").as("age")).select("name", "age"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 3))); + } + + @Test + public void testModern4() throws Exception { + final GraphTraversal expected = mg.V().match( + as("person").values("name").as("name"), + as("person").values("age").as("age"), + as("person").out("created").as("project"), + as("project").values("name").is("lop")).select("name", "age"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 4))); + } + + @Test + public void testModern5() throws Exception { + final GraphTraversal expected = mg.V().match( + as("person").values("name").as("name"), + as("person").values("age").is(29)).select("name"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 5))); + } + + @Test + public void testModern6() throws Exception { + final GraphTraversal expected = mg.V().match( + as("person").values("name").as("name"), + as("person").values("age").as("age")).where(and(as("age").is(gt(30)), as("age").is(lt(40)))). + select("name", "age"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 6))); + } + + @Test + public void testModern7() throws Exception { + final GraphTraversal expected = mg.V().match( + as("person").values("name").as("name"), + as("person").values("age").as("age")).where(or(as("age").is(lt(30)), as("age").is(gt(40)))). + select("name", "age"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 7))); + } + + @Test + public void testModern8() throws Exception { + final GraphTraversal expected = mg.V().match( + as("person").values("name").as("name"), + as("person").values("age").as("age")).where( + or(and(as("age").is(gt(30)), as("age").is(lt(40))), as("name").is("marko"))). + select("name", "age"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 8))); + } + + @Test + public void testModern9() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").values("name").as("name")).where(as("a").values("age")). + select("name"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 9))); + } + + @Test + public void testModern10() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").values("name").as("name")).where(__.not(as("a").values("age"))). + select("name"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 10))); + } + + @Test + public void testModern11() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").out("created").as("b"), + as("a").values("name").as("name")).dedup("name").select("name"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 11))); + } + + @Test + public void testModern12() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").out("created").as("b"), + as("b").values("name").as("name")).dedup(); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 12))); + } + + @Test + public void testModern13() throws Exception { + final GraphTraversal expected = mg.V().match( + as("a").out("created").as("b"), + as("a").values("name").as("c")).dedup("a", "b", "c").select("a", "b", "c"); + assertEquals(expected, convertToGremlinTraversal(modern, loadQuery("modern", 13))); + } + + /* The Crew */ + + /* @Test + public void testCrew1() throws Exception { + final GraphTraversal expected = cg.V().match( + as("a").values("name").is("daniel"), + as("a").properties("location").as("b"), + as("b").value().as("c"), + as("b").values("startTime").as("d")). + select("c", "d"); + assertEquals(expected, convertToGremlinTraversal(crew, loadQuery("crew", 1))); + } + + /* Computer Mode */ + + /* @Test + public void testModernInComputerMode() throws Exception { + final GraphTraversal expected = mc.V().match( + as("a").hasLabel("person"), + as("a").out("knows").as("b"), + as("a").out("created").as("c"), + as("b").out("created").as("c"), + as("a").values("age").as("d")).where(as("d").is(lt(30))). + select("a", "b", "c"); + assertEquals(expected, convertToGremlinTraversal(mc, loadQuery("modern", 1))); + } + + @Test + public void testCrewInComputerMode() throws Exception { + final GraphTraversal expected = cc.V().match( + as("a").values("name").is("daniel"), + as("a").properties("location").as("b"), + as("b").value().as("c"), + as("b").values("startTime").as("d")). + select("c", "d"); + assertEquals(expected, convertToGremlinTraversal(crew, loadQuery("crew", 1))); + } */ +} \ No newline at end of file