f4ffac0ecc263396400504b2a3a3b2de309a0da9
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / query / builder / QueryBuilder.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 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 package org.onap.aai.query.builder;
21
22 import org.apache.tinkerpop.gremlin.process.traversal.Path;
23 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
24 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
25 import org.apache.tinkerpop.gremlin.structure.Edge;
26 import org.apache.tinkerpop.gremlin.structure.Vertex;
27 import org.onap.aai.config.SpringContextAware;
28 import org.onap.aai.db.props.AAIProperties;
29 import org.onap.aai.exceptions.AAIException;
30 import org.onap.aai.introspection.Introspector;
31 import org.onap.aai.introspection.Loader;
32 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
33 import org.onap.aai.parsers.query.QueryParser;
34 import org.onap.aai.parsers.query.QueryParserStrategy;
35 import org.springframework.context.ApplicationContext;
36 import org.onap.aai.edges.EdgeIngestor;
37 import org.onap.aai.edges.enums.AAIDirection;
38 import org.onap.aai.edges.enums.EdgeProperty;
39 import org.onap.aai.edges.enums.EdgeType;
40
41 import javax.ws.rs.core.MultivaluedMap;
42 import java.io.UnsupportedEncodingException;
43 import java.net.URI;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47
48 /**
49  * The Class QueryBuilder.
50  */
51 public abstract class QueryBuilder<E> implements Iterator<E> {
52
53         protected final GraphTraversalSource source;
54         protected QueryParserStrategy factory = null;
55         protected Loader loader = null;
56         protected EdgeIngestor edgeRules;
57         protected boolean optimize = false;
58         protected Vertex start = null;
59
60         protected int parentStepIndex = 0;
61         protected int containerStepIndex = 0;
62         protected int stepIndex = 0;
63
64         /**
65          * Instantiates a new query builder.
66          *
67          * @param loader the loader
68          */
69         public QueryBuilder(Loader loader, GraphTraversalSource source) {
70                 this.loader = loader;
71                 this.source = source;
72                 initEdgeIngestor();
73         }
74         
75         /**
76          * Instantiates a new query builder.
77          *
78          * @param loader the loader
79          * @param start the start
80          */
81         public QueryBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
82                 this.loader = loader;
83                 this.start = start;
84                 this.source = source;
85                 initEdgeIngestor();
86         }
87
88         public void changeLoader(Loader loader) {
89                 this.loader = loader;
90         }
91
92         protected abstract QueryBuilder<E> cloneQueryAtStep(int index);
93
94         /**
95          * Gets the vertices by indexed property.
96          *
97          * @param key the key
98          * @param value the value
99          * @return the vertices by indexed property
100          */
101         public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
102                 return this.getVerticesByProperty(key, value);
103         }
104         
105         /**
106          * Gets the vertices by property.
107          *
108          * @param key the key
109          * @param value the value
110          * @return the vertices by property
111          */
112         public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, Object value);
113         
114         /**
115          * filters by all the values for this property
116          * @param key
117          * @param values
118          * @return vertices that match these values
119          */
120         public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
121                 return this.getVerticesByProperty(key, values);
122         }
123
124         /**
125          * filters by all the values for this property
126          * @param key
127          * @param values
128          * @return vertices that match these values
129          */
130         public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, List<?> values);
131         
132     /**
133      * Gets the vertices that have this property key.
134      *
135      * @param key the key
136      * @param value the value
137      * @return the vertices by property
138      */
139     public abstract QueryBuilder<Vertex> getVerticesByProperty(String key);
140     
141     /**
142      * Gets the vertices that do not have this property key.
143      *
144      * @param key the key
145      * @param value the value
146      * @return the vertices by property
147      */
148     public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key);
149
150         /**
151          * filters by elements that start with the value for this property
152          * @param key
153          * @param value
154          * @return vertices that match these values
155          */
156         public abstract QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value);
157
158         /**
159          * Gets the vertices that are excluded by property.
160          *
161          * @param key the key
162          * @param value the value
163          * @return the vertices by property
164          */
165         public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, Object value);
166
167         /**
168          * filters by all the values for this property and excludes the vertices
169          * @param key
170          * @param values
171          * @return vertices that match these values
172          */
173         public QueryBuilder<Vertex> getVerticesExcludeByIndexedProperty(String key, List<?> values) {
174                 return this.getVerticesExcludeByProperty(key, values);
175         }
176
177         /**
178          * filters by all the values for this property and excludes the vertices
179          * @param key
180          * @param values
181          * @return vertices that match these values
182          */
183         public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, List<?> values);
184
185         /**
186          * filters by all the values greater than for this property  
187      * @param key
188      * @param values
189      * @return vertices that match these values
190      */
191     public abstract  QueryBuilder<Vertex> getVerticesGreaterThanProperty(String key, Object value) ;
192
193     /**
194      * filters by all the values less than for this property 
195      * @param key
196      * @param values
197      * @return vertices that match these values
198      */
199     
200     public abstract  QueryBuilder<Vertex> getVerticesLessThanProperty(String key, Object value) ;
201
202     /**
203          * Gets the child vertices from parent.
204          *
205          * @param parentKey the parent key
206          * @param parentValue the parent value
207          * @param childType the child type
208          * @return the child vertices from parent
209          */
210         public abstract QueryBuilder<Vertex> getChildVerticesFromParent(String parentKey, String parentValue, String childType);
211                 
212         /**
213          * Gets the typed vertices by map.
214          *
215          * @param type the type
216          * @param map the map
217          * @return the typed vertices by map
218          */
219         public abstract QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map);
220
221         /**
222          * Creates the DB query.
223          *
224          * @param obj the obj
225          * @return the query builder
226          */
227         public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
228                 this.createKeyQuery(obj);
229                 this.createContainerQuery(obj);
230                 return (QueryBuilder<Vertex>) this;
231         }
232         
233         /**
234          * Creates the key query.
235          *
236          * @param obj the obj
237          * @return the query builder
238          */
239         public abstract QueryBuilder<Vertex> createKeyQuery(Introspector obj);
240         
241         /**
242          * Creates the container query.
243          *
244          * @param obj the obj
245          * @return the query builder
246          */
247         public abstract QueryBuilder<Vertex> createContainerQuery(Introspector obj);
248         
249         /**
250          * Creates the edge traversal.
251          *
252          * @param parent the parent
253          * @param child the child
254          * @return the query builder
255          */
256         public abstract QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException;
257
258         public abstract QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, Object value);
259         /**
260          * Creates the private edge traversal.
261          *
262          * @param parent the parent
263          * @param child the child
264          * @return the query builder
265          */
266         public abstract QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException;
267
268         /**
269          * Creates the edge traversal.
270          *
271          * @param parent the parent
272          * @param child the child
273          * @return the query builder
274          */
275         public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException {
276                 String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
277                 this.createEdgeTraversal(type, nodeType, child.getDbName());
278                 return (QueryBuilder<Vertex>) this;
279         }
280
281         /**
282          *
283          * @param type
284          * @param outNodeType
285          * @param inNodeType
286          * @return
287          * @throws AAIException
288          */
289         public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
290                 Introspector out = loader.introspectorFromName(outNodeType);
291                 Introspector in = loader.introspectorFromName(inNodeType);
292
293                 return createEdgeTraversal(type, out, in);
294         }
295
296         public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException {
297
298                 Introspector out = loader.introspectorFromName(outNodeType);
299                 Introspector in = loader.introspectorFromName(inNodeType);
300
301                 QueryBuilder<Vertex> cousinBuilder = null;
302                 QueryBuilder<Vertex> treeBuilder   = null;
303                 QueryBuilder<Vertex> queryBuilder  = null;
304
305                 try {
306                         cousinBuilder = this.newInstance().createEdgeTraversal(EdgeType.COUSIN, out, in);
307                 } catch (AAIException e) {
308                 }
309
310                 if(cousinBuilder != null){
311                         try {
312                                 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
313                         } catch (AAIException e) {
314                         }
315                         if(treeBuilder != null){
316                                 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder, treeBuilder});
317                         } else {
318                                 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder});
319                         }
320                 } else {
321                         treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
322                         queryBuilder = this.union(new QueryBuilder[]{treeBuilder});
323                 }
324
325
326                 return queryBuilder;
327         }
328
329         public QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
330                 Introspector out = loader.introspectorFromName(outNodeType);
331                 Introspector in = loader.introspectorFromName(inNodeType);
332                 return createPrivateEdgeTraversal(type, out, in);
333         }
334
335         /**
336          *
337          * @param type
338          * @param outNodeType
339          * @param inNodeType
340          * @param labels
341          * @return
342          * @throws AAIException
343          */
344         public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
345                 Introspector out = loader.introspectorFromName(outNodeType);
346                 Introspector in = loader.introspectorFromName(inNodeType);
347
348                 return createEdgeTraversalWithLabels(type, out, in, labels);
349         }
350
351         /**
352          *
353          * @param type
354          * @param out
355          * @param in
356          * @param labels
357          * @return
358          */
359         public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException;
360
361         /**
362          *
363          * @param type
364          * @param outNodeType
365          * @param inNodeType
366          * @return
367          * @throws AAIException
368          */
369         public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
370                 this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
371
372                 return (QueryBuilder<Edge>)this;
373
374         }
375         /**
376          *
377          * @param type
378          * @param outNodeType
379          * @param inNodeType
380          * @param labels
381          * @return
382          * @throws AAIException
383          */
384         public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException;
385
386         /**
387          * Creates the query from URI.
388          *
389          * @param uri the uri
390          * @return the query parser
391          * @throws UnsupportedEncodingException the unsupported encoding exception
392          * @throws AAIException the AAI exception
393          */
394         public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
395         
396         /**
397          * Creates the query from URI.
398          *
399          * @param uri the uri
400          * @param queryParams the query params
401          * @return the query parser
402          * @throws UnsupportedEncodingException the unsupported encoding exception
403          * @throws AAIException the AAI exception
404          */
405         public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
406
407         /**
408          * Creates a queryparser from a given object name.
409          * 
410          * @param objName - name of the object type as it appears in the database
411          * @return
412          */
413         public abstract QueryParser createQueryFromObjectName(String objName);
414         
415         /**
416          * Creates the query from relationship.
417          *
418          * @param relationship the relationship
419          * @return the query parser
420          * @throws UnsupportedEncodingException the unsupported encoding exception
421          * @throws AAIException the AAI exception
422          */
423         public abstract QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException;
424
425         /**
426          * Gets the parent query.
427          *
428          * @return the parent query
429          */
430         public abstract QueryBuilder<E> getParentQuery();
431         
432         /**
433          * Gets the query.
434          *
435          * @return the query
436          */
437         public abstract <E2> E2 getQuery();
438         
439         /**
440          * Form boundary.
441          */
442         public abstract void markParentBoundary();
443         
444         public abstract QueryBuilder<E> limit(long amount);
445
446         /**
447          * New instance.
448          *
449          * @param start the start
450          * @return the query builder
451          */
452         public abstract QueryBuilder<E> newInstance(Vertex start);
453         
454         /**
455          * New instance.
456          *
457          * @return the query builder
458          */
459         public abstract QueryBuilder<E> newInstance();
460         
461         /**
462          * Gets the start.
463          *
464          * @return the start
465          */
466         public abstract Vertex getStart();
467
468         protected Object correctObjectType(Object obj) {
469                 
470                 if (obj != null && obj.getClass().equals(Long.class)) {
471                         return new Integer(obj.toString());
472                 }
473                 
474                 return obj;
475         }
476         /**
477          * uses all fields in the introspector to create a query
478          * 
479          * @param obj
480          * @return
481          */
482         public abstract QueryBuilder<Vertex> exactMatchQuery(Introspector obj);
483
484         /**
485          * lets you join any number of QueryBuilders
486          * <b>be careful about starting with a union it will not use indexes</b>
487          * @param builder
488          * @return
489          */
490         public abstract QueryBuilder<E> union(QueryBuilder<E>... builder);
491         
492         public abstract QueryBuilder<E> where(QueryBuilder<E>... builder);
493         
494         public abstract QueryBuilder<E> or(QueryBuilder<E>... builder);
495         
496         public abstract QueryBuilder<E> store(String name);
497         public abstract QueryBuilder<E> cap(String name);
498         public abstract QueryBuilder<E> unfold();
499         public abstract QueryBuilder<E> dedup();
500         public abstract QueryBuilder<E> emit();
501         public abstract QueryBuilder<E> repeat(QueryBuilder<E> builder);
502         public abstract QueryBuilder<Edge> outE();
503         public abstract QueryBuilder<Edge> inE();
504         public abstract QueryBuilder<Vertex> inV();
505         public abstract QueryBuilder<Vertex> outV();
506         public abstract QueryBuilder<E> not(QueryBuilder<E> builder);
507         public abstract QueryBuilder<E> as(String name);
508         public abstract QueryBuilder<E> select(String name);
509         public abstract QueryBuilder<E> until(QueryBuilder<E> builder);
510         public abstract QueryBuilder<E> groupCount();
511         public abstract QueryBuilder<E> by(String name);
512         public abstract QueryBuilder<E> both();
513         public abstract QueryBuilder<Tree> tree();
514         
515         /**
516          * Used to prevent the traversal from repeating its path through the graph.
517          * See http://tinkerpop.apache.org/docs/3.0.1-incubating/#simplepath-step for more info.
518          * 
519          * @return a QueryBuilder with the simplePath step appended to its traversal
520          */
521         public abstract QueryBuilder<E> simplePath();
522
523         /**
524          *
525          * @return QueryBuilder with the path step appended to its traversal
526          */
527         public abstract QueryBuilder<Path> path();
528         
529         public abstract void markContainer();
530
531         public abstract QueryBuilder<E> getContainerQuery();
532
533         public abstract List<E> toList();
534
535         /**
536          * Used to skip step if there is an optional property missing.
537          * @param key
538          * @param value
539          * @return
540          */
541         public QueryBuilder<Vertex> getVerticesByProperty(String key, MissingOptionalParameter value) {
542                 return (QueryBuilder<Vertex>) this;
543         }
544
545         /**
546          * TODO the edge direction is hardcoded here, make it more generic
547          * Returns the parent edge of the vertex
548          * @return
549          */
550         public QueryBuilder<Edge> getParentEdge() {
551                 this.outE().has(EdgeProperty.CONTAINS.toString(), AAIDirection.IN.toString());
552                 return (QueryBuilder<Edge>)this;
553         }
554
555         /**
556          * TODO the edge direction is hardcoded here, make it more generic
557          * Returns the parent vertex of the vertex
558          * @return
559          */
560         public QueryBuilder<Vertex> getParentVertex() {
561                 this.getParentEdge().inV();
562                 return (QueryBuilder<Vertex>)this;
563         }
564
565         protected abstract QueryBuilder<Edge> has(String key, String value);
566         
567         protected void initEdgeIngestor() {
568                 //TODO proper spring wiring, but that requires a lot of refactoring so for now we have this
569                 ApplicationContext ctx = SpringContextAware.getApplicationContext();
570                 EdgeIngestor ei = ctx.getBean(EdgeIngestor.class);
571                 setEdgeIngestor(ei);
572         }
573         
574         protected void setEdgeIngestor(EdgeIngestor ei) {
575                 this.edgeRules = ei;
576         }
577 }