2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.onap.aai.query.builder;
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;
41 import javax.ws.rs.core.MultivaluedMap;
42 import java.io.UnsupportedEncodingException;
44 import java.util.Iterator;
45 import java.util.List;
49 * The Class QueryBuilder.
51 public abstract class QueryBuilder<E> implements Iterator<E> {
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;
60 protected int parentStepIndex = 0;
61 protected int containerStepIndex = 0;
62 protected int stepIndex = 0;
65 * Instantiates a new query builder.
67 * @param loader the loader
69 public QueryBuilder(Loader loader, GraphTraversalSource source) {
76 * Instantiates a new query builder.
78 * @param loader the loader
79 * @param start the start
81 public QueryBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
88 public void changeLoader(Loader loader) {
92 protected abstract QueryBuilder<E> cloneQueryAtStep(int index);
95 * Gets the vertices by indexed property.
98 * @param value the value
99 * @return the vertices by indexed property
101 public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
102 return this.getVerticesByProperty(key, value);
106 * Gets the vertices by property.
109 * @param value the value
110 * @return the vertices by property
112 public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, Object value);
115 * filters by all the values for this property
118 * @return vertices that match these values
120 public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
121 return this.getVerticesByProperty(key, values);
125 * filters by all the values for this property
128 * @return vertices that match these values
130 public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, List<?> values);
133 * Gets the vertices that have this property key.
136 * @param value the value
137 * @return the vertices by property
139 public abstract QueryBuilder<Vertex> getVerticesByProperty(String key);
142 * Gets the vertices that do not have this property key.
145 * @param value the value
146 * @return the vertices by property
148 public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key);
151 * filters by elements that start with the value for this property
154 * @return vertices that match these values
156 public abstract QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value);
159 * Gets the vertices that are excluded by property.
162 * @param value the value
163 * @return the vertices by property
165 public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, Object value);
168 * filters by all the values for this property and excludes the vertices
171 * @return vertices that match these values
173 public QueryBuilder<Vertex> getVerticesExcludeByIndexedProperty(String key, List<?> values) {
174 return this.getVerticesExcludeByProperty(key, values);
178 * filters by all the values for this property and excludes the vertices
181 * @return vertices that match these values
183 public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, List<?> values);
186 * filters by all the values greater than for this property
189 * @return vertices that match these values
191 public abstract QueryBuilder<Vertex> getVerticesGreaterThanProperty(String key, Object value) ;
194 * filters by all the values less than for this property
197 * @return vertices that match these values
200 public abstract QueryBuilder<Vertex> getVerticesLessThanProperty(String key, Object value) ;
203 * Gets the child vertices from parent.
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
210 public abstract QueryBuilder<Vertex> getChildVerticesFromParent(String parentKey, String parentValue, String childType);
213 * Gets the typed vertices by map.
215 * @param type the type
217 * @return the typed vertices by map
219 public abstract QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map);
222 * Creates the DB query.
225 * @return the query builder
227 public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
228 this.createKeyQuery(obj);
229 this.createContainerQuery(obj);
230 return (QueryBuilder<Vertex>) this;
234 * Creates the key query.
237 * @return the query builder
239 public abstract QueryBuilder<Vertex> createKeyQuery(Introspector obj);
242 * Creates the container query.
245 * @return the query builder
247 public abstract QueryBuilder<Vertex> createContainerQuery(Introspector obj);
250 * Creates the edge traversal.
252 * @param parent the parent
253 * @param child the child
254 * @return the query builder
256 public abstract QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException;
258 public abstract QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, Object value);
260 public QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, MissingOptionalParameter value) {
261 return (QueryBuilder<Vertex>) this;
264 * Creates the private edge traversal.
266 * @param parent the parent
267 * @param child the child
268 * @return the query builder
270 public abstract QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException;
273 * Creates the edge traversal.
275 * @param parent the parent
276 * @param child the child
277 * @return the query builder
279 public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException {
280 String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
281 this.createEdgeTraversal(type, nodeType, child.getDbName());
282 return (QueryBuilder<Vertex>) this;
291 * @throws AAIException
293 public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
294 Introspector out = loader.introspectorFromName(outNodeType);
295 Introspector in = loader.introspectorFromName(inNodeType);
297 return createEdgeTraversal(type, out, in);
306 * @throws AAIException
308 public QueryBuilder<Vertex> createEdgeTraversal(String edgeType, String outNodeType, String inNodeType) throws AAIException {
310 * When the optional parameter edgetype is sent it is a string that needs to be converted to Enum
312 EdgeType type = EdgeType.valueOf(edgeType);
313 Introspector out = loader.introspectorFromName(outNodeType);
314 Introspector in = loader.introspectorFromName(inNodeType);
316 return createEdgeTraversal(type, out, in);
321 * @param MissingOptionalParameter
325 * @throws AAIException
327 public QueryBuilder<Vertex> createEdgeTraversal(MissingOptionalParameter edgeType, String outNodeType, String inNodeType) throws AAIException {
329 * When no optional parameter edgetype is sent get all edges between the 2 nodetypes
331 return this.createEdgeTraversal(outNodeType, inNodeType);
334 public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException {
336 Introspector out = loader.introspectorFromName(outNodeType);
337 Introspector in = loader.introspectorFromName(inNodeType);
339 QueryBuilder<Vertex> cousinBuilder = null;
340 QueryBuilder<Vertex> treeBuilder = null;
341 QueryBuilder<Vertex> queryBuilder = null;
344 cousinBuilder = this.newInstance().createEdgeTraversal(EdgeType.COUSIN, out, in);
345 } catch (AAIException e) {
348 if(cousinBuilder != null){
350 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
351 } catch (AAIException e) {
353 if(treeBuilder != null){
354 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder, treeBuilder});
356 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder});
359 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
360 queryBuilder = this.union(new QueryBuilder[]{treeBuilder});
367 public QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
368 Introspector out = loader.introspectorFromName(outNodeType);
369 Introspector in = loader.introspectorFromName(inNodeType);
370 return createPrivateEdgeTraversal(type, out, in);
380 * @throws AAIException
382 public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
383 Introspector out = loader.introspectorFromName(outNodeType);
384 Introspector in = loader.introspectorFromName(inNodeType);
386 return createEdgeTraversalWithLabels(type, out, in, labels);
397 public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException;
405 * @throws AAIException
407 public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
408 this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
410 return (QueryBuilder<Edge>)this;
420 * @throws AAIException
422 public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException;
425 * Creates the query from URI.
428 * @return the query parser
429 * @throws UnsupportedEncodingException the unsupported encoding exception
430 * @throws AAIException the AAI exception
432 public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
435 * Creates the query from URI.
438 * @param queryParams the query params
439 * @return the query parser
440 * @throws UnsupportedEncodingException the unsupported encoding exception
441 * @throws AAIException the AAI exception
443 public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
446 * Creates a queryparser from a given object name.
448 * @param objName - name of the object type as it appears in the database
451 public abstract QueryParser createQueryFromObjectName(String objName);
454 * Creates the query from relationship.
456 * @param relationship the relationship
457 * @return the query parser
458 * @throws UnsupportedEncodingException the unsupported encoding exception
459 * @throws AAIException the AAI exception
461 public abstract QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException;
464 * Gets the parent query.
466 * @return the parent query
468 public abstract QueryBuilder<E> getParentQuery();
475 public abstract <E2> E2 getQuery();
480 public abstract void markParentBoundary();
482 public abstract QueryBuilder<E> limit(long amount);
487 * @param start the start
488 * @return the query builder
490 public abstract QueryBuilder<E> newInstance(Vertex start);
495 * @return the query builder
497 public abstract QueryBuilder<E> newInstance();
504 public abstract Vertex getStart();
506 protected Object correctObjectType(Object obj) {
508 if (obj != null && obj.getClass().equals(Long.class)) {
509 return new Integer(obj.toString());
515 * uses all fields in the introspector to create a query
520 public abstract QueryBuilder<Vertex> exactMatchQuery(Introspector obj);
523 * lets you join any number of QueryBuilders
524 * <b>be careful about starting with a union it will not use indexes</b>
528 public abstract QueryBuilder<E> union(QueryBuilder<E>... builder);
530 public abstract QueryBuilder<E> where(QueryBuilder<E>... builder);
532 public abstract QueryBuilder<E> or(QueryBuilder<E>... builder);
534 public abstract QueryBuilder<E> store(String name);
535 public abstract QueryBuilder<E> cap(String name);
536 public abstract QueryBuilder<E> unfold();
537 public abstract QueryBuilder<E> dedup();
538 public abstract QueryBuilder<E> emit();
539 public abstract QueryBuilder<E> repeat(QueryBuilder<E> builder);
540 public abstract QueryBuilder<Edge> outE();
541 public abstract QueryBuilder<Edge> inE();
542 public abstract QueryBuilder<Vertex> inV();
543 public abstract QueryBuilder<Vertex> outV();
544 public abstract QueryBuilder<E> not(QueryBuilder<E> builder);
545 public abstract QueryBuilder<E> as(String name);
546 public abstract QueryBuilder<E> select(String name);
547 public abstract QueryBuilder<E> select(String... names);
548 public abstract QueryBuilder<E> until(QueryBuilder<E> builder);
549 public abstract QueryBuilder<E> groupCount();
550 public abstract QueryBuilder<E> by(String name);
551 public abstract QueryBuilder<E> both();
552 public abstract QueryBuilder<Tree> tree();
555 * Used to prevent the traversal from repeating its path through the graph.
556 * See http://tinkerpop.apache.org/docs/3.0.1-incubating/#simplepath-step for more info.
558 * @return a QueryBuilder with the simplePath step appended to its traversal
560 public abstract QueryBuilder<E> simplePath();
564 * @return QueryBuilder with the path step appended to its traversal
566 public abstract QueryBuilder<Path> path();
568 public abstract void markContainer();
570 public abstract QueryBuilder<E> getContainerQuery();
572 public abstract List<E> toList();
575 * Used to skip step if there is an optional property missing.
580 public QueryBuilder<Vertex> getVerticesByProperty(String key, MissingOptionalParameter value) {
581 return (QueryBuilder<Vertex>) this;
585 * TODO the edge direction is hardcoded here, make it more generic
586 * Returns the parent edge of the vertex
589 public QueryBuilder<Edge> getParentEdge() {
590 this.outE().has(EdgeProperty.CONTAINS.toString(), AAIDirection.IN.toString());
591 return (QueryBuilder<Edge>)this;
595 * TODO the edge direction is hardcoded here, make it more generic
596 * Returns the parent vertex of the vertex
599 public QueryBuilder<Vertex> getParentVertex() {
600 this.getParentEdge().inV();
601 return (QueryBuilder<Vertex>)this;
604 protected abstract QueryBuilder<Edge> has(String key, String value);
606 protected void initEdgeIngestor() {
607 //TODO proper spring wiring, but that requires a lot of refactoring so for now we have this
608 ApplicationContext ctx = SpringContextAware.getApplicationContext();
609 EdgeIngestor ei = ctx.getBean(EdgeIngestor.class);
613 protected void setEdgeIngestor(EdgeIngestor ei) {
617 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, Object value) {
618 return getVerticesByProperty(key, value);
621 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key) {
622 return getVerticesByProperty(key);
625 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, MissingOptionalParameter value) {
626 return getVerticesByProperty(key, value);