777204f2cc2df892d31bae7aee576aa250410dec
[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         /**
297          *
298          * @param edgeType
299          * @param outNodeType
300          * @param inNodeType
301          * @return
302          * @throws AAIException
303          */
304         public QueryBuilder<Vertex> createEdgeTraversal(String edgeType, String outNodeType, String inNodeType) throws AAIException {
305                 /*
306                  * When the optional parameter edgetype is sent it is a string that needs to be converted to Enum
307                  */
308                 EdgeType type = EdgeType.valueOf(edgeType);
309                 Introspector out = loader.introspectorFromName(outNodeType);
310                 Introspector in = loader.introspectorFromName(inNodeType);
311
312                 return createEdgeTraversal(type, out, in);
313         }
314         
315         /**
316          *
317          * @param MissingOptionalParameter
318          * @param outNodeType
319          * @param inNodeType
320          * @return
321          * @throws AAIException
322          */
323         public QueryBuilder<Vertex> createEdgeTraversal(MissingOptionalParameter edgeType, String outNodeType, String inNodeType) throws AAIException {
324                 /*
325                  * When no optional parameter edgetype is sent get all edges between the 2 nodetypes
326                  */
327                 return this.createEdgeTraversal(outNodeType, inNodeType);       
328         }
329         
330         public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException {
331
332                 Introspector out = loader.introspectorFromName(outNodeType);
333                 Introspector in = loader.introspectorFromName(inNodeType);
334
335                 QueryBuilder<Vertex> cousinBuilder = null;
336                 QueryBuilder<Vertex> treeBuilder   = null;
337                 QueryBuilder<Vertex> queryBuilder  = null;
338
339                 try {
340                         cousinBuilder = this.newInstance().createEdgeTraversal(EdgeType.COUSIN, out, in);
341                 } catch (AAIException e) {
342                 }
343
344                 if(cousinBuilder != null){
345                         try {
346                                 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
347                         } catch (AAIException e) {
348                         }
349                         if(treeBuilder != null){
350                                 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder, treeBuilder});
351                         } else {
352                                 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder});
353                         }
354                 } else {
355                         treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
356                         queryBuilder = this.union(new QueryBuilder[]{treeBuilder});
357                 }
358
359
360                 return queryBuilder;
361         }
362
363         public QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
364                 Introspector out = loader.introspectorFromName(outNodeType);
365                 Introspector in = loader.introspectorFromName(inNodeType);
366                 return createPrivateEdgeTraversal(type, out, in);
367         }
368
369         /**
370          *
371          * @param type
372          * @param outNodeType
373          * @param inNodeType
374          * @param labels
375          * @return
376          * @throws AAIException
377          */
378         public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
379                 Introspector out = loader.introspectorFromName(outNodeType);
380                 Introspector in = loader.introspectorFromName(inNodeType);
381
382                 return createEdgeTraversalWithLabels(type, out, in, labels);
383         }
384
385         /**
386          *
387          * @param type
388          * @param out
389          * @param in
390          * @param labels
391          * @return
392          */
393         public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException;
394
395         /**
396          *
397          * @param type
398          * @param outNodeType
399          * @param inNodeType
400          * @return
401          * @throws AAIException
402          */
403         public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
404                 this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
405
406                 return (QueryBuilder<Edge>)this;
407
408         }
409         /**
410          *
411          * @param type
412          * @param outNodeType
413          * @param inNodeType
414          * @param labels
415          * @return
416          * @throws AAIException
417          */
418         public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException;
419
420         /**
421          * Creates the query from URI.
422          *
423          * @param uri the uri
424          * @return the query parser
425          * @throws UnsupportedEncodingException the unsupported encoding exception
426          * @throws AAIException the AAI exception
427          */
428         public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
429         
430         /**
431          * Creates the query from URI.
432          *
433          * @param uri the uri
434          * @param queryParams the query params
435          * @return the query parser
436          * @throws UnsupportedEncodingException the unsupported encoding exception
437          * @throws AAIException the AAI exception
438          */
439         public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
440
441         /**
442          * Creates a queryparser from a given object name.
443          * 
444          * @param objName - name of the object type as it appears in the database
445          * @return
446          */
447         public abstract QueryParser createQueryFromObjectName(String objName);
448         
449         /**
450          * Creates the query from relationship.
451          *
452          * @param relationship the relationship
453          * @return the query parser
454          * @throws UnsupportedEncodingException the unsupported encoding exception
455          * @throws AAIException the AAI exception
456          */
457         public abstract QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException;
458
459         /**
460          * Gets the parent query.
461          *
462          * @return the parent query
463          */
464         public abstract QueryBuilder<E> getParentQuery();
465         
466         /**
467          * Gets the query.
468          *
469          * @return the query
470          */
471         public abstract <E2> E2 getQuery();
472         
473         /**
474          * Form boundary.
475          */
476         public abstract void markParentBoundary();
477         
478         public abstract QueryBuilder<E> limit(long amount);
479
480         /**
481          * New instance.
482          *
483          * @param start the start
484          * @return the query builder
485          */
486         public abstract QueryBuilder<E> newInstance(Vertex start);
487         
488         /**
489          * New instance.
490          *
491          * @return the query builder
492          */
493         public abstract QueryBuilder<E> newInstance();
494         
495         /**
496          * Gets the start.
497          *
498          * @return the start
499          */
500         public abstract Vertex getStart();
501
502         protected Object correctObjectType(Object obj) {
503                 
504                 if (obj != null && obj.getClass().equals(Long.class)) {
505                         return new Integer(obj.toString());
506                 }
507                 
508                 return obj;
509         }
510         /**
511          * uses all fields in the introspector to create a query
512          * 
513          * @param obj
514          * @return
515          */
516         public abstract QueryBuilder<Vertex> exactMatchQuery(Introspector obj);
517
518         /**
519          * lets you join any number of QueryBuilders
520          * <b>be careful about starting with a union it will not use indexes</b>
521          * @param builder
522          * @return
523          */
524         public abstract QueryBuilder<E> union(QueryBuilder<E>... builder);
525         
526         public abstract QueryBuilder<E> where(QueryBuilder<E>... builder);
527         
528         public abstract QueryBuilder<E> or(QueryBuilder<E>... builder);
529         
530         public abstract QueryBuilder<E> store(String name);
531         public abstract QueryBuilder<E> cap(String name);
532         public abstract QueryBuilder<E> unfold();
533         public abstract QueryBuilder<E> dedup();
534         public abstract QueryBuilder<E> emit();
535         public abstract QueryBuilder<E> repeat(QueryBuilder<E> builder);
536         public abstract QueryBuilder<Edge> outE();
537         public abstract QueryBuilder<Edge> inE();
538         public abstract QueryBuilder<Vertex> inV();
539         public abstract QueryBuilder<Vertex> outV();
540         public abstract QueryBuilder<E> not(QueryBuilder<E> builder);
541         public abstract QueryBuilder<E> as(String name);
542         public abstract QueryBuilder<E> select(String name);
543         public abstract QueryBuilder<E> select(String... names);
544         public abstract QueryBuilder<E> until(QueryBuilder<E> builder);
545         public abstract QueryBuilder<E> groupCount();
546         public abstract QueryBuilder<E> by(String name);
547         public abstract QueryBuilder<E> both();
548         public abstract QueryBuilder<Tree> tree();
549         
550         /**
551          * Used to prevent the traversal from repeating its path through the graph.
552          * See http://tinkerpop.apache.org/docs/3.0.1-incubating/#simplepath-step for more info.
553          * 
554          * @return a QueryBuilder with the simplePath step appended to its traversal
555          */
556         public abstract QueryBuilder<E> simplePath();
557
558         /**
559          *
560          * @return QueryBuilder with the path step appended to its traversal
561          */
562         public abstract QueryBuilder<Path> path();
563         
564         public abstract void markContainer();
565
566         public abstract QueryBuilder<E> getContainerQuery();
567
568         public abstract List<E> toList();
569
570         /**
571          * Used to skip step if there is an optional property missing.
572          * @param key
573          * @param value
574          * @return
575          */
576         public QueryBuilder<Vertex> getVerticesByProperty(String key, MissingOptionalParameter value) {
577                 return (QueryBuilder<Vertex>) this;
578         }
579
580         /**
581          * TODO the edge direction is hardcoded here, make it more generic
582          * Returns the parent edge of the vertex
583          * @return
584          */
585         public QueryBuilder<Edge> getParentEdge() {
586                 this.outE().has(EdgeProperty.CONTAINS.toString(), AAIDirection.IN.toString());
587                 return (QueryBuilder<Edge>)this;
588         }
589
590         /**
591          * TODO the edge direction is hardcoded here, make it more generic
592          * Returns the parent vertex of the vertex
593          * @return
594          */
595         public QueryBuilder<Vertex> getParentVertex() {
596                 this.getParentEdge().inV();
597                 return (QueryBuilder<Vertex>)this;
598         }
599
600         protected abstract QueryBuilder<Edge> has(String key, String value);
601         
602         protected void initEdgeIngestor() {
603                 //TODO proper spring wiring, but that requires a lot of refactoring so for now we have this
604                 ApplicationContext ctx = SpringContextAware.getApplicationContext();
605                 EdgeIngestor ei = ctx.getBean(EdgeIngestor.class);
606                 setEdgeIngestor(ei);
607         }
608         
609         protected void setEdgeIngestor(EdgeIngestor ei) {
610                 this.edgeRules = ei;
611         }
612
613         public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, Object value) {
614                 return getVerticesByProperty(key, value);
615         }
616
617     public QueryBuilder<Vertex> getVerticesByNumberProperty(String key) {
618         return getVerticesByProperty(key);
619     }
620     
621     public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, MissingOptionalParameter value) {
622                 return getVerticesByProperty(key, value);
623         }
624 }