ATLAS-2520: Introduce JanusGraphTraversal to deprecate use of GremlinScriptEngine
Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/942a5382 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/942a5382 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/942a5382 Branch: refs/heads/branch-1.0 Commit: 942a5382c9517b8ebe9ed1f99def6bacd9c6a706 Parents: 6973830 Author: apoorvnaik <apoorvn...@apache.org> Authored: Tue Oct 23 15:39:29 2018 -0700 Committer: Ashutosh Mestry <ames...@hortonworks.com> Committed: Thu Nov 1 15:42:58 2018 -0700 ---------------------------------------------------------------------- graphdb/api/pom.xml | 5 + .../atlas/repository/graphdb/AtlasGraph.java | 21 +- .../repository/graphdb/AtlasGraphTraversal.java | 91 ++++++++ .../graphdb/AtlasGraphTraversalSource.java | 40 ++++ .../graphdb/janus/AtlasJanusGraph.java | 19 ++ .../graphdb/janus/AtlasJanusGraphTraversal.java | 232 +++++++++++++++++++ .../org/apache/atlas/query/GremlinQuery.java | 18 +- 7 files changed, 409 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/graphdb/api/pom.xml ---------------------------------------------------------------------- diff --git a/graphdb/api/pom.xml b/graphdb/api/pom.xml index e13c4cb..6e0f050 100644 --- a/graphdb/api/pom.xml +++ b/graphdb/api/pom.xml @@ -46,6 +46,11 @@ <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-core</artifactId> + <version>3.3.3</version> + </dependency> </dependencies> http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java index 31d2085..09eab28 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java @@ -17,18 +17,17 @@ */ package org.apache.atlas.repository.graphdb; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.groovy.GroovyExpression; +import org.apache.atlas.type.AtlasType; + +import javax.script.ScriptEngine; +import javax.script.ScriptException; import java.io.IOException; import java.io.OutputStream; import java.util.Map; import java.util.Set; -import javax.script.ScriptEngine; -import javax.script.ScriptException; - -import org.apache.atlas.exception.AtlasBaseException; -import org.apache.atlas.groovy.GroovyExpression; -import org.apache.atlas.type.AtlasType; - /** * Represents a graph. * @@ -144,6 +143,14 @@ public interface AtlasGraph<V, E> { AtlasGraphQuery<V, E> query(); /** + * Start a graph traversal + * @return + */ + AtlasGraphTraversal<AtlasVertex, AtlasEdge> V(Object ... vertexIds); + + AtlasGraphTraversal<AtlasVertex, AtlasEdge> E(Object ... edgeIds); + + /** * Creates an index query. * * @param indexName index name http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversal.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversal.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversal.java new file mode 100644 index 0000000..881bb1e --- /dev/null +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversal.java @@ -0,0 +1,91 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.atlas.repository.graphdb; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Graph; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiPredicate; + + +public abstract class AtlasGraphTraversal<V extends AtlasVertex, E extends AtlasEdge> extends DefaultGraphTraversal { + + protected AtlasGraph atlasGraph; + + // For anonymous/inner traversal + public AtlasGraphTraversal() { + } + + public AtlasGraphTraversal(final AtlasGraph atlasGraph, final Graph graph) { + super(graph); + this.atlasGraph = atlasGraph; + } + + public AtlasGraphTraversal(final AtlasGraph atlasGraph, final GraphTraversalSource traversalSource) { + super(traversalSource); + this.atlasGraph = atlasGraph; + } + + public abstract AtlasGraphTraversal startAnonymousTraversal(); + + public abstract List<V> getAtlasVertexList(); + + public abstract Set<V> getAtlasVertexSet(); + + public abstract Map<String, Collection<V>> getAtlasVertexMap(); + + public abstract List<E> getAtlasEdgeList(); + + public abstract Set<E> getAtlasEdgeSet(); + + public abstract Map<String, E> getAtlasEdgeMap(); + + public abstract TextPredicate textPredicate(); + + public interface TextPredicate { + + /** + * Whether the text contains a given term as a token in the text (case insensitive) + */ + BiPredicate contains(); + + /** + * Whether the text contains a token that starts with a given term (case insensitive) + */ + BiPredicate containsPrefix(); + /** + * Whether the text contains a token that matches a regular expression + */ + BiPredicate containsRegex(); + + /** + * Whether the text starts with a given prefix (case sensitive) + */ + BiPredicate prefix(); + + /** + * Whether the text matches a regular expression (case sensitive) + */ + BiPredicate regex(); + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversalSource.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversalSource.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversalSource.java new file mode 100644 index 0000000..cabe2ba --- /dev/null +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphTraversalSource.java @@ -0,0 +1,40 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.atlas.repository.graphdb; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Transaction; + +public interface AtlasGraphTraversalSource<V extends AtlasVertex, E extends AtlasEdge> { + + // Concrete implementations need to have graph and graphTraversal source + Graph getGraph(); + + GraphTraversalSource getGraphTraversalSource(); + + AtlasGraphTraversal<V, E> startAnonymousTraversal(); + + AtlasGraphTraversal<V, E> V(final Object... vertexIds); + + AtlasGraphTraversal<V, E> E(final Object... edgesIds); + + Transaction tx(); + + void close() throws Exception; +} http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java ---------------------------------------------------------------------- diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java index dc1f011..9328414 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java @@ -29,6 +29,7 @@ import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasGraphManagement; import org.apache.atlas.repository.graphdb.AtlasGraphQuery; +import org.apache.atlas.repository.graphdb.AtlasGraphTraversal; import org.apache.atlas.repository.graphdb.AtlasIndexQuery; import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException; import org.apache.atlas.repository.graphdb.AtlasVertex; @@ -40,7 +41,9 @@ import org.apache.commons.configuration.Configuration; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer; import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; import org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; @@ -127,6 +130,22 @@ public class AtlasJanusGraph implements AtlasGraph<AtlasJanusVertex, AtlasJanusE } @Override + public AtlasGraphTraversal<AtlasVertex, AtlasEdge> V(final Object... vertexIds) { + AtlasGraphTraversal traversal = new AtlasJanusGraphTraversal(this, getGraph().traversal()); + traversal.getBytecode().addStep(GraphTraversal.Symbols.V, vertexIds); + traversal.addStep(new GraphStep<>(traversal, Vertex.class, true, vertexIds)); + return traversal; + } + + @Override + public AtlasGraphTraversal<AtlasVertex, AtlasEdge> E(final Object... edgeIds) { + AtlasGraphTraversal traversal = new AtlasJanusGraphTraversal(this, getGraph().traversal()); + traversal.getBytecode().addStep(GraphTraversal.Symbols.E, edgeIds); + traversal.addStep(new GraphStep<>(traversal, Vertex.class, true, edgeIds)); + return traversal; + } + + @Override public AtlasEdge<AtlasJanusVertex, AtlasJanusEdge> getEdge(String edgeId) { Iterator<Edge> it = getGraph().edges(edgeId); Edge e = getSingleElement(it, edgeId); http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTraversal.java ---------------------------------------------------------------------- diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTraversal.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTraversal.java new file mode 100644 index 0000000..c33c4f4 --- /dev/null +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTraversal.java @@ -0,0 +1,232 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.atlas.repository.graphdb.janus; + +import org.apache.atlas.repository.graphdb.AtlasGraph; +import org.apache.atlas.repository.graphdb.AtlasGraphTraversal; +import org.apache.commons.collections.CollectionUtils; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.attribute.Text; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiPredicate; + +public class AtlasJanusGraphTraversal extends AtlasGraphTraversal<AtlasJanusVertex, AtlasJanusEdge> { + + private List resultList; + private Set resultSet; + + public AtlasJanusGraphTraversal() { + } + + public AtlasJanusGraphTraversal(final AtlasGraph<AtlasJanusVertex, AtlasJanusEdge> atlasGraph, + final GraphTraversalSource traversalSource) { + super(atlasGraph, traversalSource); + } + + public AtlasJanusGraphTraversal(final AtlasGraph atlasGraph, final Graph graph) { + super(atlasGraph, graph); + } + + @Override + public AtlasGraphTraversal startAnonymousTraversal() { + return new AtlasJanusGraphTraversal(); + } + + @Override + public List<AtlasJanusVertex> getAtlasVertexList() { + List list = getResultList(); + List<AtlasJanusVertex> ret; + + if (CollectionUtils.isNotEmpty(list)) { + // toList called after groupBy will return a single map element list + if (list.size() == 1 && list.get(0) instanceof Map) { + ret = Collections.emptyList(); + } else { + ret = new ArrayList<>(list.size()); + for (Object o : list) { + if (o instanceof Vertex) { + ret.add(GraphDbObjectFactory.createVertex((AtlasJanusGraph) atlasGraph, (Vertex) o)); + } + } + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + + @Override + public Set<AtlasJanusVertex> getAtlasVertexSet() { + Set set = getResultSet(); + Set<AtlasJanusVertex> ret; + + if (CollectionUtils.isNotEmpty(set)) { + ret = new HashSet<>(set.size()); + for (Object o : set) { + if (o instanceof Vertex) { + ret.add(GraphDbObjectFactory.createVertex((AtlasJanusGraph) atlasGraph, (Vertex) o)); + } + } + } else { + ret = Collections.emptySet(); + } + + return ret; + } + + @Override + public Map<String, Collection<AtlasJanusVertex>> getAtlasVertexMap() { + List list = getResultList(); + Map<String, Collection<AtlasJanusVertex>> ret; + + if (CollectionUtils.isNotEmpty(list)) { + ret = new HashMap<>(list.size()); + if (list.size() == 1 && list.get(0) instanceof Map) { + Map aMap = (Map) list.get(0); + for (Object key : aMap.keySet()) { + + if (!(key instanceof String)) { + continue; + } + + Object value = aMap.get(key); + if (value instanceof List) { + Collection<AtlasJanusVertex> values = new ArrayList<>(); + for (Object o : (List) value) { + if (o instanceof Vertex) { + values.add(GraphDbObjectFactory.createVertex((AtlasJanusGraph) atlasGraph, (Vertex) o)); + } + } + ret.put((String) key, values); + } + } + } + } else { + ret = Collections.emptyMap(); + } + + return ret; + } + + @Override + public List<AtlasJanusEdge> getAtlasEdgeList() { + List list = getResultList(); + List<AtlasJanusEdge> ret; + + if (CollectionUtils.isNotEmpty(list)) { + if (list.size() == 1 && list.get(0) instanceof Map) { + ret = Collections.emptyList(); + } else { + ret = new ArrayList<>(list.size()); + for (Object o : list) { + if (o instanceof Edge) { + ret.add(GraphDbObjectFactory.createEdge((AtlasJanusGraph) atlasGraph, (Edge) o)); + } + } + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + + @Override + public Set<AtlasJanusEdge> getAtlasEdgeSet() { + Set set = getResultSet(); + Set<AtlasJanusEdge> ret; + + if (CollectionUtils.isNotEmpty(set)) { + ret = new HashSet<>(set.size()); + for (Object o : set) { + if (o instanceof Edge) { + ret.add(GraphDbObjectFactory.createEdge((AtlasJanusGraph) atlasGraph, (Edge) o)); + } + } + } else { + ret = Collections.emptySet(); + } + + return ret; + } + + @Override + public Map<String, AtlasJanusEdge> getAtlasEdgeMap() { + return null; + } + + @Override + public TextPredicate textPredicate() { + return new JanusGraphPredicate(); + } + + + public static class JanusGraphPredicate implements TextPredicate { + @Override + public BiPredicate<Object, Object> contains() { + return Text.CONTAINS; + } + + @Override + public BiPredicate<Object, Object> containsPrefix() { + return Text.CONTAINS_PREFIX; + } + + @Override + public BiPredicate<Object, Object> containsRegex() { + return Text.CONTAINS_REGEX; + } + + @Override + public BiPredicate<Object, Object> prefix() { + return Text.PREFIX; + } + + @Override + public BiPredicate<Object, Object> regex() { + return Text.REGEX; + } + } + + private List getResultList() { + if (resultList == null) { + resultList = toList(); + } + return resultList; + } + + private Set getResultSet() { + if (resultSet == null) { + resultSet = toSet(); + } + return resultSet; + } + +} http://git-wip-us.apache.org/repos/asf/atlas/blob/942a5382/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java b/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java index 3b8de08..531f7ae 100644 --- a/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java +++ b/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java @@ -6,9 +6,9 @@ * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> + * + * 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. @@ -18,7 +18,6 @@ package org.apache.atlas.query; public class GremlinQuery { - private final String queryStr; private final boolean hasSelect; @@ -27,12 +26,11 @@ public class GremlinQuery { this.hasSelect = hasSelect; } - - public boolean hasSelectList() { - return this.hasSelect; - } - public String queryStr() { return queryStr; } -} + + public boolean hasSelectList() { + return hasSelect; + } +} \ No newline at end of file