contains-other-v no longer implies delete-other-v
[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().has(DELETE_OTHER_V.toString(), OUT.toString()).inV(),
117                                                 __.inE().has(DELETE_OTHER_V.toString(), IN.toString()).outV()
118                                         )
119                                 );
120                 
121                 return pipe.toList();
122         }
123
124         /**
125          * {@inheritDoc}
126          */
127         @Override
128         public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
129                 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start);
130                 switch (direction) {
131                         case OUT:
132                                 pipe.out(label);
133                                 break;
134                         case IN:
135                                 pipe.in(label);
136                                 break;
137                         case BOTH:
138                                 pipe.both(label);
139                                 break;
140                          default:
141                                 break;
142                 }
143                 
144                 pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
145                 return pipe.toList();
146         }
147         
148         @Override
149         public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) {
150                 final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat(
151                                 __.union(
152                                         __.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
153                                         __.inE().has(CONTAINS.toString(), IN.toString()).outV())
154                                 );
155                         
156                 if (!nodeOnly) {
157                         t.union(
158                                         __.identity(),
159                                         __.bothE().has(CONTAINS.toString(), NONE.toString()).dedup().otherV()
160                         );
161                 }
162                 t.tree();
163                 if (t.hasNext()) {
164                         return (Tree)t.next();
165                 } else {
166                         return new Tree();
167                 }
168         }
169
170         @Override
171         public List<Edge> findEdgesForVersion(Vertex start, Loader loader) {
172                 final Set<String> objects = loader.getAllObjects().keySet();
173                 GraphTraversal<Vertex, Edge> pipeline = this.g.V(start).union(
174                                 __.inE().has(CONTAINS.toString(), NONE.toString()).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))),
175                                 __.outE().has(CONTAINS.toString(), NONE.toString()).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects)))
176                         ).dedup();
177                 
178                 return pipeline.toList();
179         }
180
181
182         @Override
183         public List<Vertex> findCousinVertices(Vertex start) {
184                 GraphTraversal<Vertex, Vertex> pipeline = this.g.V(start).union(
185                                 __.inE().has(CONTAINS.toString(), NONE.toString()),
186                                 __.outE().has(CONTAINS.toString(), NONE.toString())).otherV().dedup();
187                                 
188                 return pipeline.toList();
189         }
190         
191 }
192