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 * Creates the private edge traversal.
262 * @param parent the parent
263 * @param child the child
264 * @return the query builder
266 public abstract QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException;
269 * Creates the edge traversal.
271 * @param parent the parent
272 * @param child the child
273 * @return the query builder
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;
287 * @throws AAIException
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);
293 return createEdgeTraversal(type, out, in);
302 * @throws AAIException
304 public QueryBuilder<Vertex> createEdgeTraversal(String edgeType, String outNodeType, String inNodeType) throws AAIException {
306 * When the optional parameter edgetype is sent it is a string that needs to be converted to Enum
308 EdgeType type = EdgeType.valueOf(edgeType);
309 Introspector out = loader.introspectorFromName(outNodeType);
310 Introspector in = loader.introspectorFromName(inNodeType);
312 return createEdgeTraversal(type, out, in);
317 * @param MissingOptionalParameter
321 * @throws AAIException
323 public QueryBuilder<Vertex> createEdgeTraversal(MissingOptionalParameter edgeType, String outNodeType, String inNodeType) throws AAIException {
325 * When no optional parameter edgetype is sent get all edges between the 2 nodetypes
327 return this.createEdgeTraversal(outNodeType, inNodeType);
330 public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException {
332 Introspector out = loader.introspectorFromName(outNodeType);
333 Introspector in = loader.introspectorFromName(inNodeType);
335 QueryBuilder<Vertex> cousinBuilder = null;
336 QueryBuilder<Vertex> treeBuilder = null;
337 QueryBuilder<Vertex> queryBuilder = null;
340 cousinBuilder = this.newInstance().createEdgeTraversal(EdgeType.COUSIN, out, in);
341 } catch (AAIException e) {
344 if(cousinBuilder != null){
346 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
347 } catch (AAIException e) {
349 if(treeBuilder != null){
350 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder, treeBuilder});
352 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder});
355 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
356 queryBuilder = this.union(new QueryBuilder[]{treeBuilder});
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);
376 * @throws AAIException
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);
382 return createEdgeTraversalWithLabels(type, out, in, labels);
393 public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException;
401 * @throws AAIException
403 public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
404 this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
406 return (QueryBuilder<Edge>)this;
416 * @throws AAIException
418 public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException;
421 * Creates the query from URI.
424 * @return the query parser
425 * @throws UnsupportedEncodingException the unsupported encoding exception
426 * @throws AAIException the AAI exception
428 public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
431 * Creates the query from 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
439 public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
442 * Creates a queryparser from a given object name.
444 * @param objName - name of the object type as it appears in the database
447 public abstract QueryParser createQueryFromObjectName(String objName);
450 * Creates the query from relationship.
452 * @param relationship the relationship
453 * @return the query parser
454 * @throws UnsupportedEncodingException the unsupported encoding exception
455 * @throws AAIException the AAI exception
457 public abstract QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException;
460 * Gets the parent query.
462 * @return the parent query
464 public abstract QueryBuilder<E> getParentQuery();
471 public abstract <E2> E2 getQuery();
476 public abstract void markParentBoundary();
478 public abstract QueryBuilder<E> limit(long amount);
483 * @param start the start
484 * @return the query builder
486 public abstract QueryBuilder<E> newInstance(Vertex start);
491 * @return the query builder
493 public abstract QueryBuilder<E> newInstance();
500 public abstract Vertex getStart();
502 protected Object correctObjectType(Object obj) {
504 if (obj != null && obj.getClass().equals(Long.class)) {
505 return new Integer(obj.toString());
511 * uses all fields in the introspector to create a query
516 public abstract QueryBuilder<Vertex> exactMatchQuery(Introspector obj);
519 * lets you join any number of QueryBuilders
520 * <b>be careful about starting with a union it will not use indexes</b>
524 public abstract QueryBuilder<E> union(QueryBuilder<E>... builder);
526 public abstract QueryBuilder<E> where(QueryBuilder<E>... builder);
528 public abstract QueryBuilder<E> or(QueryBuilder<E>... builder);
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();
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.
554 * @return a QueryBuilder with the simplePath step appended to its traversal
556 public abstract QueryBuilder<E> simplePath();
560 * @return QueryBuilder with the path step appended to its traversal
562 public abstract QueryBuilder<Path> path();
564 public abstract void markContainer();
566 public abstract QueryBuilder<E> getContainerQuery();
568 public abstract List<E> toList();
571 * Used to skip step if there is an optional property missing.
576 public QueryBuilder<Vertex> getVerticesByProperty(String key, MissingOptionalParameter value) {
577 return (QueryBuilder<Vertex>) this;
581 * TODO the edge direction is hardcoded here, make it more generic
582 * Returns the parent edge of the vertex
585 public QueryBuilder<Edge> getParentEdge() {
586 this.outE().has(EdgeProperty.CONTAINS.toString(), AAIDirection.IN.toString());
587 return (QueryBuilder<Edge>)this;
591 * TODO the edge direction is hardcoded here, make it more generic
592 * Returns the parent vertex of the vertex
595 public QueryBuilder<Vertex> getParentVertex() {
596 this.getParentEdge().inV();
597 return (QueryBuilder<Vertex>)this;
600 protected abstract QueryBuilder<Edge> has(String key, String value);
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);
609 protected void setEdgeIngestor(EdgeIngestor ei) {
613 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, Object value) {
614 return getVerticesByProperty(key, value);
617 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key) {
618 return getVerticesByProperty(key);
621 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, MissingOptionalParameter value) {
622 return getVerticesByProperty(key, value);