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);
296 public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException {
298 Introspector out = loader.introspectorFromName(outNodeType);
299 Introspector in = loader.introspectorFromName(inNodeType);
301 QueryBuilder<Vertex> cousinBuilder = null;
302 QueryBuilder<Vertex> treeBuilder = null;
303 QueryBuilder<Vertex> queryBuilder = null;
306 cousinBuilder = this.newInstance().createEdgeTraversal(EdgeType.COUSIN, out, in);
307 } catch (AAIException e) {
310 if(cousinBuilder != null){
312 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
313 } catch (AAIException e) {
315 if(treeBuilder != null){
316 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder, treeBuilder});
318 queryBuilder = this.union(new QueryBuilder[]{cousinBuilder});
321 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
322 queryBuilder = this.union(new QueryBuilder[]{treeBuilder});
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);
342 * @throws AAIException
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);
348 return createEdgeTraversalWithLabels(type, out, in, labels);
359 public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException;
367 * @throws AAIException
369 public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
370 this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
372 return (QueryBuilder<Edge>)this;
382 * @throws AAIException
384 public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException;
387 * Creates the query from URI.
390 * @return the query parser
391 * @throws UnsupportedEncodingException the unsupported encoding exception
392 * @throws AAIException the AAI exception
394 public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
397 * Creates the query from 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
405 public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
408 * Creates a queryparser from a given object name.
410 * @param objName - name of the object type as it appears in the database
413 public abstract QueryParser createQueryFromObjectName(String objName);
416 * Creates the query from relationship.
418 * @param relationship the relationship
419 * @return the query parser
420 * @throws UnsupportedEncodingException the unsupported encoding exception
421 * @throws AAIException the AAI exception
423 public abstract QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException;
426 * Gets the parent query.
428 * @return the parent query
430 public abstract QueryBuilder<E> getParentQuery();
437 public abstract <E2> E2 getQuery();
442 public abstract void markParentBoundary();
444 public abstract QueryBuilder<E> limit(long amount);
449 * @param start the start
450 * @return the query builder
452 public abstract QueryBuilder<E> newInstance(Vertex start);
457 * @return the query builder
459 public abstract QueryBuilder<E> newInstance();
466 public abstract Vertex getStart();
468 protected Object correctObjectType(Object obj) {
470 if (obj != null && obj.getClass().equals(Long.class)) {
471 return new Integer(obj.toString());
477 * uses all fields in the introspector to create a query
482 public abstract QueryBuilder<Vertex> exactMatchQuery(Introspector obj);
485 * lets you join any number of QueryBuilders
486 * <b>be careful about starting with a union it will not use indexes</b>
490 public abstract QueryBuilder<E> union(QueryBuilder<E>... builder);
492 public abstract QueryBuilder<E> where(QueryBuilder<E>... builder);
494 public abstract QueryBuilder<E> or(QueryBuilder<E>... builder);
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();
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.
519 * @return a QueryBuilder with the simplePath step appended to its traversal
521 public abstract QueryBuilder<E> simplePath();
525 * @return QueryBuilder with the path step appended to its traversal
527 public abstract QueryBuilder<Path> path();
529 public abstract void markContainer();
531 public abstract QueryBuilder<E> getContainerQuery();
533 public abstract List<E> toList();
536 * Used to skip step if there is an optional property missing.
541 public QueryBuilder<Vertex> getVerticesByProperty(String key, MissingOptionalParameter value) {
542 return (QueryBuilder<Vertex>) this;
546 * TODO the edge direction is hardcoded here, make it more generic
547 * Returns the parent edge of the vertex
550 public QueryBuilder<Edge> getParentEdge() {
551 this.outE().has(EdgeProperty.CONTAINS.toString(), AAIDirection.IN.toString());
552 return (QueryBuilder<Edge>)this;
556 * TODO the edge direction is hardcoded here, make it more generic
557 * Returns the parent vertex of the vertex
560 public QueryBuilder<Vertex> getParentVertex() {
561 this.getParentEdge().inV();
562 return (QueryBuilder<Vertex>)this;
565 protected abstract QueryBuilder<Edge> has(String key, String value);
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);
574 protected void setEdgeIngestor(EdgeIngestor ei) {