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=========================================================
21 package org.onap.aai.query.builder;
23 import java.io.UnsupportedEncodingException;
25 import java.util.Iterator;
26 import java.util.List;
29 import javax.ws.rs.core.MultivaluedMap;
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;
51 * The Class QueryBuilder.
53 public abstract class QueryBuilder<E> implements Iterator<E> {
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;
62 protected int parentStepIndex = 0;
63 protected int containerStepIndex = 0;
64 protected int stepIndex = 0;
67 * Instantiates a new query builder.
69 * @param loader the loader
71 public QueryBuilder(Loader loader, GraphTraversalSource source) {
78 * Instantiates a new query builder.
80 * @param loader the loader
81 * @param start the start
83 public QueryBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
90 public void changeLoader(Loader loader) {
94 protected abstract QueryBuilder<E> cloneQueryAtStep(int index);
97 * Gets the vertices by indexed property.
100 * @param value the value
101 * @return the vertices by indexed property
103 public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
104 return this.getVerticesByProperty(key, value);
108 * Gets the vertices by property.
111 * @param value the value
112 * @return the vertices by property
114 public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, Object value);
117 * filters by all the values for this property
121 * @return vertices that match these values
123 public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
124 return this.getVerticesByProperty(key, values);
128 * filters by all the values for this property
132 * @return vertices that match these values
134 public abstract QueryBuilder<Vertex> getVerticesByProperty(String key, List<?> values);
137 * Gets the vertices that have this property key.
140 * @param value the value
141 * @return the vertices by property
143 public abstract QueryBuilder<Vertex> getVerticesByProperty(String key);
146 * Gets the vertices that do not have this property key.
149 * @param value the value
150 * @return the vertices by property
152 public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key);
155 * filters by elements that start with the value for this property
159 * @return vertices that match these values
161 public abstract QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value);
164 * Gets the vertices that are excluded by property.
167 * @param value the value
168 * @return the vertices by property
170 public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, Object value);
173 * filters by all the values for this property and excludes the vertices
177 * @return vertices that match these values
179 public QueryBuilder<Vertex> getVerticesExcludeByIndexedProperty(String key, List<?> values) {
180 return this.getVerticesExcludeByProperty(key, values);
184 * filters by all the values for this property and excludes the vertices
188 * @return vertices that match these values
190 public abstract QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, List<?> values);
193 * filters by all the values greater than for this property
197 * @return vertices that match these values
199 public abstract QueryBuilder<Vertex> getVerticesGreaterThanProperty(String key, Object value);
202 * filters by all the values less than for this property
206 * @return vertices that match these values
209 public abstract QueryBuilder<Vertex> getVerticesLessThanProperty(String key, Object value);
212 * Gets the child vertices from parent.
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
219 public abstract QueryBuilder<Vertex> getChildVerticesFromParent(String parentKey, String parentValue,
223 * Gets the typed vertices by map.
225 * @param type the type
227 * @return the typed vertices by map
229 public abstract QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map);
232 * Creates the DB query.
235 * @return the query builder
237 public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
238 this.createKeyQuery(obj);
239 this.createContainerQuery(obj);
240 return (QueryBuilder<Vertex>) this;
244 * Creates the key query.
247 * @return the query builder
249 public abstract QueryBuilder<Vertex> createKeyQuery(Introspector obj);
252 * Creates the container query.
255 * @return the query builder
257 public abstract QueryBuilder<Vertex> createContainerQuery(Introspector obj);
260 * Creates the edge traversal.
262 * @param parent the parent
263 * @param child the child
264 * @return the query builder
266 public abstract QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Introspector parent, Introspector child)
269 public abstract QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, Object value);
271 public QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, MissingOptionalParameter value) {
272 return (QueryBuilder<Vertex>) this;
276 * Creates the private edge traversal.
278 * @param parent the parent
279 * @param child the child
280 * @return the query builder
282 public abstract QueryBuilder<Vertex> createPrivateEdgeTraversal(EdgeType type, Introspector parent,
283 Introspector child) throws AAIException;
286 * Creates the edge traversal.
288 * @param parent the parent
289 * @param child the child
290 * @return the query builder
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;
305 * @throws AAIException
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);
312 return createEdgeTraversal(type, out, in);
321 * @throws AAIException
323 public QueryBuilder<Vertex> createEdgeTraversal(String edgeType, String outNodeType, String inNodeType)
324 throws AAIException {
326 * When the optional parameter edgetype is sent it is a string that needs to be converted to Enum
328 EdgeType type = EdgeType.valueOf(edgeType);
329 Introspector out = loader.introspectorFromName(outNodeType);
330 Introspector in = loader.introspectorFromName(inNodeType);
332 return createEdgeTraversal(type, out, in);
337 * @param MissingOptionalParameter
341 * @throws AAIException
343 public QueryBuilder<Vertex> createEdgeTraversal(MissingOptionalParameter edgeType, String outNodeType,
344 String inNodeType) throws AAIException {
346 * When no optional parameter edgetype is sent get all edges between the 2 nodetypes
348 return this.createEdgeTraversal(outNodeType, inNodeType);
351 public QueryBuilder<Vertex> createEdgeTraversal(String outNodeType, String inNodeType) throws AAIException {
353 Introspector out = loader.introspectorFromName(outNodeType);
354 Introspector in = loader.introspectorFromName(inNodeType);
356 QueryBuilder<Vertex> cousinBuilder = null;
357 QueryBuilder<Vertex> treeBuilder = null;
358 QueryBuilder<Vertex> queryBuilder = null;
361 cousinBuilder = this.newInstance().createEdgeTraversal(EdgeType.COUSIN, out, in);
362 } catch (AAIException e) {
365 if (cousinBuilder != null) {
367 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
368 } catch (AAIException e) {
370 if (treeBuilder != null) {
371 queryBuilder = this.union(new QueryBuilder[] {cousinBuilder, treeBuilder});
373 queryBuilder = this.union(new QueryBuilder[] {cousinBuilder});
376 treeBuilder = this.newInstance().createEdgeTraversal(EdgeType.TREE, out, in);
377 queryBuilder = this.union(new QueryBuilder[] {treeBuilder});
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);
397 * @throws AAIException
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);
404 return createEdgeTraversalWithLabels(type, out, in, labels);
415 public abstract QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in,
416 List<String> labels) throws AAIException;
424 * @throws AAIException
426 public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType)
427 throws AAIException {
428 this.getEdgesBetweenWithLabels(type, outNodeType, inNodeType, null);
430 return (QueryBuilder<Edge>) this;
441 * @throws AAIException
443 public abstract QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType,
444 List<String> labels) throws AAIException;
447 * Creates the query from URI.
450 * @return the query parser
451 * @throws UnsupportedEncodingException the unsupported encoding exception
452 * @throws AAIException the AAI exception
454 public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
457 * Creates the query from 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
465 public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams)
466 throws UnsupportedEncodingException, AAIException;
469 * Creates a queryparser from a given object name.
471 * @param objName - name of the object type as it appears in the database
474 public abstract QueryParser createQueryFromObjectName(String objName);
477 * Creates the query from relationship.
479 * @param relationship the relationship
480 * @return the query parser
481 * @throws UnsupportedEncodingException the unsupported encoding exception
482 * @throws AAIException the AAI exception
484 public abstract QueryParser createQueryFromRelationship(Introspector relationship)
485 throws UnsupportedEncodingException, AAIException;
488 * Gets the parent query.
490 * @return the parent query
492 public abstract QueryBuilder<E> getParentQuery();
499 public abstract <E2> E2 getQuery();
504 public abstract void markParentBoundary();
506 public abstract QueryBuilder<E> limit(long amount);
511 * @param start the start
512 * @return the query builder
514 public abstract QueryBuilder<E> newInstance(Vertex start);
519 * @return the query builder
521 public abstract QueryBuilder<E> newInstance();
528 public abstract Vertex getStart();
530 protected Object correctObjectType(Object obj) {
532 if (obj != null && obj.getClass().equals(Long.class)) {
533 return new Integer(obj.toString());
540 * uses all fields in the introspector to create a query
545 public abstract QueryBuilder<Vertex> exactMatchQuery(Introspector obj);
548 * lets you join any number of QueryBuilders
549 * <b>be careful about starting with a union it will not use indexes</b>
554 public abstract QueryBuilder<E> union(QueryBuilder<E>... builder);
556 public abstract QueryBuilder<E> where(QueryBuilder<E>... builder);
558 public abstract QueryBuilder<E> or(QueryBuilder<E>... builder);
560 public abstract QueryBuilder<E> store(String name);
562 public abstract QueryBuilder<E> cap(String name);
564 public abstract QueryBuilder<E> unfold();
566 public abstract QueryBuilder<E> dedup();
568 public abstract QueryBuilder<E> emit();
570 public abstract QueryBuilder<E> repeat(QueryBuilder<E> builder);
572 public abstract QueryBuilder<Edge> outE();
574 public abstract QueryBuilder<Edge> inE();
576 public abstract QueryBuilder<Vertex> inV();
578 public abstract QueryBuilder<Vertex> outV();
580 public abstract QueryBuilder<E> not(QueryBuilder<E> builder);
582 public abstract QueryBuilder<E> as(String name);
584 public abstract QueryBuilder<E> select(String name);
586 public abstract QueryBuilder<E> select(String... names);
588 public abstract QueryBuilder<E> until(QueryBuilder<E> builder);
590 public abstract QueryBuilder<E> groupCount();
592 public abstract QueryBuilder<E> by(String name);
594 public abstract QueryBuilder<E> both();
596 public abstract QueryBuilder<Tree> tree();
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.
602 * @return a QueryBuilder with the simplePath step appended to its traversal
604 public abstract QueryBuilder<E> simplePath();
608 * @return QueryBuilder with the path step appended to its traversal
610 public abstract QueryBuilder<Path> path();
612 public abstract void markContainer();
614 public abstract QueryBuilder<E> getContainerQuery();
616 public abstract List<E> toList();
619 * Used to skip step if there is an optional property missing.
625 public QueryBuilder<Vertex> getVerticesByProperty(String key, MissingOptionalParameter value) {
626 return (QueryBuilder<Vertex>) this;
630 * TODO the edge direction is hardcoded here, make it more generic
631 * Returns the parent edge of the vertex
635 public QueryBuilder<Edge> getParentEdge() {
636 this.outE().has(EdgeProperty.CONTAINS.toString(), AAIDirection.IN.toString());
637 return (QueryBuilder<Edge>) this;
641 * TODO the edge direction is hardcoded here, make it more generic
642 * Returns the parent vertex of the vertex
646 public QueryBuilder<Vertex> getParentVertex() {
647 this.getParentEdge().inV();
648 return (QueryBuilder<Vertex>) this;
651 protected abstract QueryBuilder<Edge> has(String key, String value);
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);
660 protected void setEdgeIngestor(EdgeIngestor ei) {
664 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, Object value) {
665 return getVerticesByProperty(key, value);
668 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key) {
669 return getVerticesByProperty(key);
672 public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, MissingOptionalParameter value) {
673 return getVerticesByProperty(key, value);