872b0c5f457554e014361765f97efe18362f8f8d
[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
46 /*
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.
53  * 
54  */
55 public class GraphTraversalQueryEngine extends QueryEngine {
56
57         /**
58          * Instantiates a new graph traversal query engine.
59          *
60          * @param graphEngine the graph engine
61          */
62         public GraphTraversalQueryEngine(GraphTraversalSource g) {
63                 super(g);
64         }
65
66         /**
67          * {@inheritDoc}
68          */
69         @Override
70         public List<Vertex> findParents(Vertex start) {
71                 
72                 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()));
73                 return pipe.toList();
74         }
75
76         /**
77          * {@inheritDoc}
78          */
79         @Override
80         public List<Vertex> findAllChildren(Vertex start) {
81                 
82                 GraphTraversal<Vertex, Vertex> pipe =  this.g
83                                 .V(start).emit(v -> true).repeat(__.union(__.outE().has(CONTAINS.toString(), OUT.toString()).inV(), __.inE().has(CONTAINS.toString(), IN.toString()).outV()));
84                 
85
86                 return pipe.toList();
87                 
88         }
89
90         public List<Vertex> findChildrenOfType(Vertex start, String type) {
91                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
92                                         __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
93                                         __.inE().has(CONTAINS.toString(), IN.toString()).outV()
94                                 ).has(AAIProperties.NODE_TYPE, type).dedup();
95  
96                 return pipe.toList();
97         }
98         
99         public List<Vertex> findChildren(Vertex start) {
100                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
101                                         __.outE().has(CONTAINS.toString(), OUT.toString()),
102                                         __.inE().has(CONTAINS.toString(), IN.toString())
103                                 ).otherV().dedup();
104  
105                 return pipe.toList();
106         }
107
108         /**
109          * {@inheritDoc}
110          */
111         @Override
112         public List<Vertex> findDeletable(Vertex start) {
113                 GraphTraversal<Vertex, Vertex> pipe = this.g
114                                 .V(start).emit(v -> true).repeat(
115                                         __.union(
116                                                 __.outE().or(
117                                                         __.has(CONTAINS.toString(), OUT.toString()),
118                                                         __.has(DELETE_OTHER_V.toString(), OUT.toString())
119                                                 ).inV(),
120                                                 __.inE().or(
121                                                                 __.has(CONTAINS.toString(), IN.toString()),
122                                                                 __.has(DELETE_OTHER_V.toString(), IN.toString())
123                                                 ).outV()
124                                         )
125                                 );
126                 
127                 return pipe.toList();
128         }
129
130         /**
131          * {@inheritDoc}
132          */
133         @Override
134         public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
135                 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start);
136                 switch (direction) {
137                         case OUT:
138                                 pipe.out(label);
139                                 break;
140                         case IN:
141                                 pipe.in(label);
142                                 break;
143                         case BOTH:
144                                 pipe.both(label);
145                                 break;
146                          default:
147                                 break;
148                 }
149                 
150                 pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
151                 return pipe.toList();
152         }
153         
154         @Override
155         public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) {
156                 final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat(
157                                 __.union(
158                                         __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
159                                         __.inE().has(CONTAINS.toString(), IN.toString()).outV())
160                                 );
161                         
162                 if (!nodeOnly) {
163                         t.union(
164                                         __.identity(),
165                                         __.bothE().has(CONTAINS.toString(), NONE.toString()).dedup().otherV()
166                         );
167                 }
168                 t.tree();
169                 if (t.hasNext()) {
170                         return (Tree)t.next();
171                 } else {
172                         return new Tree();
173                 }
174         }
175
176         @Override
177         public List<Edge> findEdgesForVersion(Vertex start, Loader loader) {
178                 final Set<String> objects = loader.getAllObjects().keySet();
179                 GraphTraversal<Vertex, Edge> pipeline = this.g.V(start).union(
180                                 __.inE().has(CONTAINS.toString(), NONE.toString()).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))),
181                                 __.outE().has(CONTAINS.toString(), NONE.toString()).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects)))
182                         ).dedup();
183                 
184                 return pipeline.toList();
185         }
186
187
188         @Override
189         public List<Vertex> findCousinVertices(Vertex start) {
190                 GraphTraversal<Vertex, Vertex> pipeline = this.g.V(start).union(
191                                 __.inE().has(CONTAINS.toString(), NONE.toString()),
192                                 __.outE().has(CONTAINS.toString(), NONE.toString())).otherV().dedup();
193                                 
194                 return pipeline.toList();
195         }
196         
197 }
198