2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.aai.serialization.engines.query;
23 import static org.onap.aai.edges.enums.AAIDirection.IN;
24 import static org.onap.aai.edges.enums.AAIDirection.NONE;
25 import static org.onap.aai.edges.enums.AAIDirection.OUT;
26 import static org.onap.aai.edges.enums.EdgeField.PRIVATE;
27 import static org.onap.aai.edges.enums.EdgeProperty.CONTAINS;
28 import static org.onap.aai.edges.enums.EdgeProperty.DELETE_OTHER_V;
30 import java.util.List;
33 import org.apache.tinkerpop.gremlin.process.traversal.P;
34 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
35 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
36 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
37 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
38 import org.apache.tinkerpop.gremlin.structure.Direction;
39 import org.apache.tinkerpop.gremlin.structure.Edge;
40 import org.apache.tinkerpop.gremlin.structure.Element;
41 import org.apache.tinkerpop.gremlin.structure.Vertex;
42 import org.onap.aai.db.props.AAIProperties;
43 import org.onap.aai.introspection.Loader;
44 import org.onap.aai.logging.StopWatch;
47 * This class needs some big explanation despite its compact size.
48 * This controls all the queries performed by the CRUD API in A&AI.
49 * findParents, findChildren, and findDeletable require special attention
50 * These methods use 'repeat'. You cannot use 'emit' with repeat currently
51 * as it is extremely buggy as of tinkerpop-3.0.1-incubating. The way around
52 * it (for now) is to sideEffect all the vertices we traverse into an ArrayList.
55 public class GraphTraversalQueryEngine extends QueryEngine {
58 * Instantiates a new graph traversal query engine.
60 * @param graphEngine the graph engine
62 public GraphTraversalQueryEngine(GraphTraversalSource g) {
70 public List<Vertex> findParents(Vertex start) {
72 StopWatch.conditionalStart();
73 @SuppressWarnings("unchecked")
74 final GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).emit(v -> true).repeat(__.union(__.inE().has(CONTAINS.toString(), OUT.toString()).outV(), __.outE().has(CONTAINS.toString(), IN.toString()).inV()));
78 dbTimeMsecs += StopWatch.stopIfStarted();
86 public List<Vertex> findAllChildren(Vertex start) {
88 @SuppressWarnings("unchecked")
89 GraphTraversal<Vertex, Vertex> pipe = this.g
90 .V(start).emit(v -> true).repeat(__.union(__.outE().has(CONTAINS.toString(), OUT.toString()).inV(), __.inE().has(CONTAINS.toString(), IN.toString()).outV()));
101 public List<Vertex> findChildrenOfType(Vertex start, String type) {
102 @SuppressWarnings("unchecked")
103 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).union(
104 __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
105 __.inE().has(CONTAINS.toString(), IN.toString()).outV()
106 ).has(AAIProperties.NODE_TYPE, type).dedup();
108 return pipe.toList();
115 public List<Vertex> findChildren(Vertex start) {
116 @SuppressWarnings("unchecked")
117 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).union(
118 __.outE().has(CONTAINS.toString(), OUT.toString()),
119 __.inE().has(CONTAINS.toString(), IN.toString())
122 return pipe.toList();
129 public List<Vertex> findDeletable(Vertex start) {
130 @SuppressWarnings("unchecked")
131 GraphTraversal<Vertex, Vertex> pipe = this.g
132 .V(start).emit(v -> true).repeat(
134 __.outE().has(DELETE_OTHER_V.toString(), OUT.toString()).inV(),
135 __.inE().has(DELETE_OTHER_V.toString(), IN.toString()).outV()
139 return pipe.toList();
146 public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
147 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start);
162 pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
163 return pipe.toList();
167 public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) {
168 final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat(
170 __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
171 __.inE().has(CONTAINS.toString(), IN.toString()).outV())
177 __.bothE().has(CONTAINS.toString(), NONE.toString()).dedup().otherV()
182 return (Tree)t.next();
189 public List<Edge> findEdgesForVersion(Vertex start, Loader loader) {
190 // From the given start vertex find both the
191 // out edges that has property CONTAINS set to NONE
192 // whose in vertexes has an object that is declared in the oxm
193 // And do the same thing vice versa to get a list of edges
194 // Then check that the edge should not have the property private set to true
195 // and remove the duplicates and return the list of edges
196 final Set<String> objects = loader.getAllObjects().keySet();
197 GraphTraversal<Vertex, Edge> pipeline = this.g
200 __.inE().has(CONTAINS.toString(), NONE.toString()).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))),
201 __.outE().has(CONTAINS.toString(), NONE.toString()).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects)))
204 __.has("private", true)
208 return pipeline.toList();
213 public List<Vertex> findCousinVertices(Vertex start) {
214 // Start at the given vertex
215 // Do a union to copy the start vertex to be run against all
216 // so for the start vertex it gets all of in edges that contains other v set to none
217 // and also all the other out edges with contains other v set to none
218 // And filter the edges based on the property private not set
219 // so that means it will be a regular edge
220 // and find the other end of the vertex so if setup like this:
223 GraphTraversal<Vertex, Vertex> pipeline = this.g
226 __.inE().has(CONTAINS.toString(), NONE.toString()),
227 __.outE().has(CONTAINS.toString(), NONE.toString())
230 __.has(PRIVATE.toString(), true)
235 return pipeline.toList();
238 public double getDBTimeMsecs() {
239 return (dbTimeMsecs);