a1967223dd6c08e656f8704f28cacc052cee9324
[aai/aai-common.git] / aai-core / src / main / java / org / openecomp / aai / serialization / engines / query / GraphTraversalQueryEngine.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.openecomp.aai
4  * ================================================================================
5  * Copyright (C) 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
21 package org.openecomp.aai.serialization.engines.query;
22
23 import java.util.List;
24 import java.util.Set;
25
26 import org.apache.tinkerpop.gremlin.process.traversal.P;
27 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
28 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
29 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
30 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
31 import org.apache.tinkerpop.gremlin.structure.Direction;
32 import org.apache.tinkerpop.gremlin.structure.Edge;
33 import org.apache.tinkerpop.gremlin.structure.Element;
34 import org.apache.tinkerpop.gremlin.structure.Vertex;
35 import org.openecomp.aai.db.props.AAIProperties;
36 import org.openecomp.aai.introspection.Loader;
37 import org.openecomp.aai.serialization.db.EdgeProperties;
38 import org.openecomp.aai.serialization.db.EdgeProperty;
39
40 /*
41  * This class needs some big explanation despite its compact size.
42  * This controls all the queries performed by the CRUD API in A&AI. 
43  * findParents, findChildren, and findDeletable require special attention
44  *   These methods use 'repeat'. You cannot use 'emit' with repeat currently
45  *   as it is extremely buggy as of tinkerpop-3.0.1-incubating. The way around
46  *   it (for now) is to sideEffect all the vertices we traverse into an ArrayList.
47  * 
48  */
49 public class GraphTraversalQueryEngine extends QueryEngine {
50
51         /**
52          * Instantiates a new graph traversal query engine.
53          *
54          * @param graphEngine the graph engine
55          */
56         public GraphTraversalQueryEngine(GraphTraversalSource g) {
57                 super(g);
58         }
59
60         /**
61          * {@inheritDoc}
62          */
63         @Override
64         public List<Vertex> findParents(Vertex start) {
65                 
66                 final GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).emit(v -> true).repeat(__.union(__.inE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).outV(), __.outE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).inV()));
67                 return pipe.toList();
68         }
69
70         /**
71          * {@inheritDoc}
72          */
73         @Override
74         public List<Vertex> findAllChildren(Vertex start) {
75                 
76                 GraphTraversal<Vertex, Vertex> pipe =  this.g
77                                 .V(start).emit(v -> true).repeat(__.union(__.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).inV(), __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).outV()));
78                 
79
80                 return pipe.toList();
81                 
82         }
83
84         public List<Vertex> findChildrenOfType(Vertex start, String type) {
85                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
86                                         __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).inV(),
87                                         __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).outV()
88                                 ).has(AAIProperties.NODE_TYPE, type).dedup();
89  
90                 return pipe.toList();
91         }
92         
93         public List<Vertex> findChildren(Vertex start) {
94                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
95                                         __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true),
96                                         __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true)
97                                 ).otherV().dedup();
98  
99                 return pipe.toList();
100         }
101
102         /**
103          * {@inheritDoc}
104          */
105         @Override
106         public List<Vertex> findDeletable(Vertex start) {
107                 GraphTraversal<Vertex, Vertex> pipe = this.g
108                                 .V(start).emit(v -> true).repeat(
109                                         __.union(
110                                                 __.outE().or(
111                                                         __.has(EdgeProperties.out(EdgeProperty.IS_PARENT), true),
112                                                         __.has(EdgeProperties.out(EdgeProperty.HAS_DEL_TARGET), true)
113                                                 ).inV(),
114                                                 __.inE().or(
115                                                                 __.has(EdgeProperties.in(EdgeProperty.IS_PARENT), true),
116                                                                 __.has(EdgeProperties.in(EdgeProperty.HAS_DEL_TARGET), true)
117                                                 ).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(EdgeProperties.out(EdgeProperty.IS_PARENT), true).inV(),
153                                         __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).outV())
154                                 );
155                         
156                 if (!nodeOnly) {
157                         t.union(
158                                         __.identity(),
159                                         __.bothE().and(__.has(EdgeProperties.out(EdgeProperty.IS_PARENT), false), __.has(EdgeProperties.in(EdgeProperty.IS_PARENT), false)).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(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))),
175                                 __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false).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(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false),
186                                 __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false)).otherV().dedup();
187                                 
188                 return pipeline.toList();
189         }
190         
191 }
192