27733039cb6382a0cc889183628bc8f7062e2c15
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / serialization / engines / query / GraphTraversalQueryEngine.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017 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
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  *
20  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22 package org.onap.aai.serialization.engines.query;
23
24
25 import static org.onap.aai.serialization.db.AAIDirection.IN;
26 import static org.onap.aai.serialization.db.AAIDirection.NONE;
27 import static org.onap.aai.serialization.db.AAIDirection.OUT;
28 import static org.onap.aai.serialization.db.EdgeProperty.CONTAINS;
29 import static org.onap.aai.serialization.db.EdgeProperty.DELETE_OTHER_V;
30
31 import java.util.List;
32 import java.util.Set;
33
34 import org.apache.tinkerpop.gremlin.process.traversal.P;
35 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
36 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
37 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
38 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
39 import org.apache.tinkerpop.gremlin.structure.Direction;
40 import org.apache.tinkerpop.gremlin.structure.Edge;
41 import org.apache.tinkerpop.gremlin.structure.Element;
42 import org.apache.tinkerpop.gremlin.structure.Vertex;
43 import org.onap.aai.db.props.AAIProperties;
44 import org.onap.aai.introspection.Loader;
45 import org.onap.aai.logging.StopWatch;
46
47 /*
48  * This class needs some big explanation despite its compact size.
49  * This controls all the queries performed by the CRUD API in A&AI. 
50  * findParents, findChildren, and findDeletable require special attention
51  *   These methods use 'repeat'. You cannot use 'emit' with repeat currently
52  *   as it is extremely buggy as of tinkerpop-3.0.1-incubating. The way around
53  *   it (for now) is to sideEffect all the vertices we traverse into an ArrayList.
54  * 
55  */
56 public class GraphTraversalQueryEngine extends QueryEngine {
57
58         /**
59          * Instantiates a new graph traversal query engine.
60          *
61          * @param graphEngine the graph engine
62          */
63         public GraphTraversalQueryEngine(GraphTraversalSource g) {
64                 super(g);
65         }
66
67         /**
68          * {@inheritDoc}
69          */
70         @Override
71         public List<Vertex> findParents(Vertex start) {
72                 try {
73                         StopWatch.conditionalStart();
74                         @SuppressWarnings("unchecked")
75                         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()));
76                         return pipe.toList();
77                 }
78                 finally {
79                         dbTimeMsecs += StopWatch.stopIfStarted();
80                 }
81         }
82
83         /**
84          * {@inheritDoc}
85          */
86         @Override
87         public List<Vertex> findAllChildren(Vertex start) {
88                 
89                 @SuppressWarnings("unchecked")
90                 GraphTraversal<Vertex, Vertex> pipe =  this.g
91                                 .V(start).emit(v -> true).repeat(__.union(__.outE().has(CONTAINS.toString(), OUT.toString()).inV(), __.inE().has(CONTAINS.toString(), IN.toString()).outV()));
92                 
93
94                 return pipe.toList();
95                 
96         }
97
98         /**
99          * {@inheritDoc}
100          */
101         @Override
102         public List<Vertex> findChildrenOfType(Vertex start, String type) {
103                 @SuppressWarnings("unchecked")
104                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
105                                         __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
106                                         __.inE().has(CONTAINS.toString(), IN.toString()).outV()
107                                 ).has(AAIProperties.NODE_TYPE, type).dedup();
108  
109                 return pipe.toList();
110         }
111         
112         /**
113          * {@inheritDoc}
114          */
115         @Override
116         public List<Vertex> findChildren(Vertex start) {
117                 @SuppressWarnings("unchecked")
118                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
119                                         __.outE().has(CONTAINS.toString(), OUT.toString()),
120                                         __.inE().has(CONTAINS.toString(), IN.toString())
121                                 ).otherV().dedup();
122  
123                 return pipe.toList();
124         }
125
126         /**
127          * {@inheritDoc}
128          */
129         @Override
130         public List<Vertex> findDeletable(Vertex start) {
131                 @SuppressWarnings("unchecked")
132                 GraphTraversal<Vertex, Vertex> pipe = this.g
133                                 .V(start).emit(v -> true).repeat(
134                                         __.union(
135                                                 __.outE().has(DELETE_OTHER_V.toString(), OUT.toString()).inV(),
136                                                 __.inE().has(DELETE_OTHER_V.toString(), IN.toString()).outV()
137                                         )
138                                 ).dedup();
139                 
140                 return pipe.toList();
141         }
142
143         /**
144          * {@inheritDoc}
145          */
146         @Override
147         public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
148                 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start);
149                 switch (direction) {
150                         case OUT:
151                                 pipe.out(label);
152                                 break;
153                         case IN:
154                                 pipe.in(label);
155                                 break;
156                         case BOTH:
157                                 pipe.both(label);
158                                 break;
159                          default:
160                                 break;
161                 }
162                 
163                 pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
164                 return pipe.toList();
165         }
166         
167         @Override
168         public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) {
169                 final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat(
170                                 __.union(
171                                         __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
172                                         __.inE().has(CONTAINS.toString(), IN.toString()).outV())
173                                 );
174                         
175                 if (!nodeOnly) {
176                         t.union(
177                                         __.identity(),
178                                         __.bothE().has(CONTAINS.toString(), NONE.toString()).dedup().otherV()
179                         );
180                 }
181                 t.tree();
182                 if (t.hasNext()) {
183                         return (Tree)t.next();
184                 } else {
185                         return new Tree();
186                 }
187         }
188
189         @Override
190         public List<Edge> findEdgesForVersion(Vertex start, Loader loader) {
191                 final Set<String> objects = loader.getAllObjects().keySet();
192                 GraphTraversal<Vertex, Edge> pipeline = this.g.V(start).union(
193                                 __.inE().has(CONTAINS.toString(), NONE.toString()).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))),
194                                 __.outE().has(CONTAINS.toString(), NONE.toString()).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects)))
195                         ).dedup();
196                 
197                 return pipeline.toList();
198         }
199
200
201         @Override
202         public List<Vertex> findCousinVertices(Vertex start) {
203                 GraphTraversal<Vertex, Vertex> pipeline = this.g.V(start).union(
204                                 __.inE().has(CONTAINS.toString(), NONE.toString()),
205                                 __.outE().has(CONTAINS.toString(), NONE.toString())).otherV().dedup();
206                                 
207                 return pipeline.toList();
208         }
209         
210         public double getDBTimeMsecs() {
211                 return (dbTimeMsecs);
212         }
213 }
214