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