2f485b1094c3d1e2c23612275f9e58a895463703
[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
36 import org.openecomp.aai.db.props.AAIProperties;
37 import org.openecomp.aai.introspection.Loader;
38
39 /*
40  * This class needs some big explanation despite its compact size.
41  * This controls all the queries performed by the CRUD API in A&AI. 
42  * findParents, findChildren, and findDeletable require special attention
43  *   These methods use 'repeat'. You cannot use 'emit' with repeat currently
44  *   as it is extremely buggy as of tinkerpop-3.0.1-incubating. The way around
45  *   it (for now) is to sideEffect all the vertices we traverse into an ArrayList.
46  * 
47  */
48 public class GraphTraversalQueryEngine extends QueryEngine {
49
50         /**
51          * Instantiates a new graph traversal query engine.
52          *
53          * @param graphEngine the graph engine
54          */
55         public GraphTraversalQueryEngine(GraphTraversalSource g) {
56                 super(g);
57         }
58
59         /**
60          * {@inheritDoc}
61          */
62         @Override
63         public List<Vertex> findParents(Vertex start) {
64                 
65                 final GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).emit(v -> true).repeat(__.inE().has("isParent", true).outV());
66                 return pipe.toList();
67         }
68
69         /**
70          * {@inheritDoc}
71          */
72         @Override
73         public List<Vertex> findAllChildren(Vertex start) {
74                 
75                 GraphTraversal<Vertex, Vertex> pipe =  this.g
76                                 .V(start).emit(v -> true).repeat(__.outE().has("isParent", true).inV());
77                 
78
79                 return pipe.toList();
80                 
81         }
82
83         public List<Vertex> findChildrenOfType(Vertex start, String type) {
84                 GraphTraversal<Vertex, Vertex> pipe =  this.g.V(start).union(
85                                         __.outE().has("isParent", true).inV(),
86                                         __.inE().has("isParent-REV", true).outV()
87                                 ).has(AAIProperties.NODE_TYPE, type).dedup();
88  
89                 return pipe.toList();
90         }
91
92         /**
93          * {@inheritDoc}
94          */
95         @Override
96         public List<Vertex> findDeletable(Vertex start) {
97                 GraphTraversal<Vertex, Vertex> pipe = this.g
98                                 .V(start).emit(v -> true).repeat(__.outE().or(
99                                                 __.has("isParent", true),
100                                                 __.has("hasDelTarget", true)).inV());
101                 
102                 return pipe.toList();
103         }
104
105         /**
106          * {@inheritDoc}
107          */
108         @Override
109         public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
110                 GraphTraversal<Vertex, Vertex> pipe = this.g.V(start);
111                 switch (direction) {
112                         case OUT:
113                                 pipe.out(label);
114                                 break;
115                         case IN:
116                                 pipe.in(label);
117                                 break;
118                         case BOTH:
119                                 pipe.both(label);
120                                 break;
121                          default:
122                                 break;
123                 }
124                 
125                 pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
126                 return pipe.toList();
127         }
128         
129         @Override
130         public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) {
131                 final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat(
132                                 __.outE().has("isParent", true).inV());
133                         
134                 if (!nodeOnly) {
135                         t.union(
136                                         __.identity(),
137                                         __.bothE().has("isParent", false).dedup().otherV()
138                         );
139                 }
140                 t.tree();
141                 if (t.hasNext()) {
142                         return (Tree)t.next();
143                 } else {
144                         return new Tree();
145                 }
146         }
147
148         @Override
149         public List<Edge> findEdgesForVersion(Vertex start, Loader loader) {
150                 final Set<String> objects = loader.getAllObjects().keySet();
151                 GraphTraversal<Vertex, Edge> pipeline = this.g.V(start).union(
152                                 __.inE().has("isParent", false).has("isParent-REV", false).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))),
153                                 __.outE().has("isParent", false).has("isParent-REV", false).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects)))
154                         ).dedup();
155                 
156                 return pipeline.toList();
157         }
158
159
160         @Override
161         public List<Vertex> findCousinVertices(Vertex start) {
162                 GraphTraversal<Vertex, Vertex> pipeline = this.g.V(start).union(
163                                 __.inE().has("isParent", false).has("isParent-REV", false),
164                                 __.outE().has("isParent", false).has("isParent-REV", false)).otherV().dedup();
165                                 
166                 return pipeline.toList();
167         }
168         
169 }
170