2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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.openecomp.aai.query.builder;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.LinkedHashMap;
26 import java.util.List;
30 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
31 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
32 import org.apache.tinkerpop.gremlin.structure.Direction;
33 import org.apache.tinkerpop.gremlin.structure.Edge;
34 import org.apache.tinkerpop.gremlin.structure.Vertex;
36 import org.openecomp.aai.db.props.AAIProperties;
37 import org.openecomp.aai.exceptions.AAIException;
38 import org.openecomp.aai.introspection.Introspector;
39 import org.openecomp.aai.introspection.Loader;
40 import org.openecomp.aai.restcore.search.GremlinGroovyShellSingleton;
41 import org.openecomp.aai.schema.enums.ObjectMetadata;
42 import org.openecomp.aai.serialization.db.EdgeRule;
43 import org.openecomp.aai.serialization.db.EdgeRules;
44 import org.openecomp.aai.serialization.db.EdgeType;
45 import org.openecomp.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
46 import com.google.common.base.Joiner;
49 * The Class GremlinQueryBuilder.
51 public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
53 private EdgeRules edgeRules = EdgeRules.getInstance();
54 private GremlinGroovyShellSingleton gremlinGroovy = GremlinGroovyShellSingleton.getInstance();
55 private GraphTraversal<?, ?> completeTraversal = null;
56 protected List<String> list = null;
58 protected int parentStepIndex = 0;
59 protected int containerStepIndex = 0;
60 protected int stepIndex = 0;
63 * Instantiates a new gremlin query builder.
65 * @param loader the loader
67 public GremlinQueryBuilder(Loader loader, GraphTraversalSource source) {
68 super(loader, source);
69 list = new ArrayList<String>();
73 * Instantiates a new gremlin query builder.
75 * @param loader the loader
76 * @param start the start
78 public GremlinQueryBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
79 super(loader, source, start);
80 list = new ArrayList<String>();
87 public QueryBuilder<Vertex> createDBQuery(Introspector obj) {
88 this.createKeyQuery(obj);
89 this.createContainerQuery(obj);
90 return (QueryBuilder<Vertex>) this;
94 public QueryBuilder<Vertex> exactMatchQuery(Introspector obj) {
95 // TODO not implemented because this is implementation is no longer used
96 this.createKeyQuery(obj);
97 //allPropertiesQuery(obj);
98 this.createContainerQuery(obj);
99 return (QueryBuilder<Vertex>) this;
106 public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, Object value) {
107 return this.getVerticesByProperty(key, value);
114 public QueryBuilder<Vertex> getVerticesByIndexedProperty(String key, List<?> values) {
115 return this.getVerticesByProperty(key, values);
122 public QueryBuilder<Vertex> getVerticesByProperty(String key, Object value) {
125 if (value != null && !value.getClass().getName().equals("java.lang.String")) {
126 term = value.toString();
128 term = "'" + value + "'";
130 list.add(".has('" + key + "', " + term + ")");
132 return (QueryBuilder<Vertex>) this;
139 public QueryBuilder<Vertex> getVerticesByProperty(String key, List<?> values) {
142 String predicate = "P.within(#!#argument#!#)";
143 List<String> arguments = new ArrayList<>();
144 for (Object item : values) {
145 if (item != null && !item.getClass().getName().equals("java.lang.String")) {
146 arguments.add(item.toString());
148 arguments.add("'" + item + "'");
151 String argument = Joiner.on(",").join(arguments);
152 predicate = predicate.replace("#!#argument#!#", argument);
153 list.add(".has('" + key + "', " + predicate + ")");
155 return (QueryBuilder<Vertex>) this;
163 public QueryBuilder<Vertex> getChildVerticesFromParent(String parentKey, String parentValue, String childType) {
165 String query = ".has('aai-node-type', '" + childType + "')";
167 return this.processGremlinQuery(parentKey, parentValue, query);
170 return (QueryBuilder<Vertex>) this;
177 public QueryBuilder<Vertex> getTypedVerticesByMap(String type, LinkedHashMap<String, String> map) {
179 for (String key : map.keySet()) {
180 list.add(".has('" + key + "', '" + map.get(key) + "')");
183 list.add(".has('aai-node-type', '" + type + "')");
185 return (QueryBuilder<Vertex>) this;
192 public QueryBuilder<Vertex> createKeyQuery(Introspector obj) {
193 Set<String> keys = obj.getKeys();
195 for (String key : keys) {
197 this.getVerticesByProperty(key, obj.<Object>getValue(key));
200 return (QueryBuilder<Vertex>) this;
204 * @throws NoEdgeRuleFoundException
205 * @throws AAIException
209 public QueryBuilder createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
210 String parentName = parent.getDbName();
211 String childName = child.getDbName();
212 if (parent.isContainer()) {
213 parentName = parent.getChildDBName();
215 if (child.isContainer()) {
216 childName = child.getChildDBName();
218 this.edgeQueryToVertex(type, parentName, childName);
224 * @throws NoEdgeRuleFoundException
225 * @throws AAIException
229 public QueryBuilder<Vertex> createEdgeTraversal(EdgeType type, Vertex parent, Introspector child) throws AAIException, NoEdgeRuleFoundException {
230 String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
231 this.edgeQueryToVertex(type, nodeType, child.getDbName());
233 return (QueryBuilder<Vertex>) this;
238 public QueryBuilder<Edge> getEdgesBetween(EdgeType type, String outNodeType, String inNodeType) throws AAIException {
239 this.edgeQuery(type, outNodeType, inNodeType);
241 return (QueryBuilder<Edge>)this;
247 * @param outType the out type
248 * @param inType the in type
249 * @throws NoEdgeRuleFoundException
250 * @throws AAIException
252 private void edgeQueryToVertex(EdgeType type, String outType, String inType) throws AAIException, NoEdgeRuleFoundException {
253 markParentBoundary();
254 EdgeRule rule = edgeRules.getEdgeRule(type, outType, inType);
255 if (rule.getDirection().equals(Direction.OUT)) {
256 list.add(".out('" + rule.getLabel() + "')");
258 list.add(".in('" + rule.getLabel() + "')");
261 list.add(".has('" + AAIProperties.NODE_TYPE + "', '" + inType + "')");
269 * @param outType the out type
270 * @param inType the in type
271 * @throws NoEdgeRuleFoundException
272 * @throws AAIException
274 private void edgeQuery(EdgeType type, String outType, String inType) throws AAIException, NoEdgeRuleFoundException {
275 markParentBoundary();
276 EdgeRule rule = edgeRules.getEdgeRule(type, outType, inType);
277 if (rule.getDirection().equals(Direction.OUT)) {
278 list.add(".outE('" + rule.getLabel() + "')");
280 list.add(".inV('" + rule.getLabel() + "')");
286 public QueryBuilder<E> limit(long amount) {
287 list.add(".limit(" + amount + ")");
294 public QueryBuilder<Vertex> createContainerQuery(Introspector obj) {
295 String type = obj.getChildDBName();
296 String abstractType = obj.getMetadata(ObjectMetadata.ABSTRACT);
297 if (abstractType != null) {
298 String[] inheritors = obj.getMetadata(ObjectMetadata.INHERITORS).split(",");
299 String[] wrapped = new String[inheritors.length];
300 StringBuilder command = new StringBuilder();
301 command.append("P.within(");
302 for (int i = 0; i < inheritors.length; i++) {
303 wrapped[i] = "'" + inheritors[i] + "'";
305 command.append(Joiner.on(",").join(wrapped));
307 list.add(".has('aai-node-type', " + command + ")");
310 list.add(".has('aai-node-type', '" + type + "')");
313 this.markContainer();
314 return (QueryBuilder<Vertex>) this;
318 public QueryBuilder<E> union(QueryBuilder<E>... builder) {
319 markParentBoundary();
320 String[] traversals = new String[builder.length];
321 StringBuilder command = new StringBuilder();
322 for (int i = 0; i < builder.length; i++) {
323 traversals[i] = "__" + (String)builder[i].getQuery();
325 command.append(".union(");
326 command.append(Joiner.on(",").join(traversals));
328 list.add(command.toString());
335 public QueryBuilder<E> where(QueryBuilder<E>... builder) {
336 markParentBoundary();
337 List<String> traversals = new ArrayList<>();
338 for (int i = 0; i < builder.length; i++) {
339 traversals.add(".where(__" + (String)builder[i].getQuery() + ")");
342 list.addAll(traversals);
352 public QueryBuilder<E> getParentQuery() {
353 return cloneQueryAtStep(parentStepIndex);
357 public QueryBuilder<E> getContainerQuery() {
358 return cloneQueryAtStep(containerStepIndex);
365 public <T2> T2 getQuery() {
366 StringBuilder sb = new StringBuilder();
368 for (String piece : this.list) {
372 return (T2)sb.toString();
379 public void markParentBoundary() {
380 parentStepIndex = stepIndex;
384 public void markContainer() {
385 this.containerStepIndex = stepIndex;
388 protected abstract QueryBuilder<E> cloneQueryAtStep(int index);
393 public Vertex getStart() {
397 protected int getParentStepIndex() {
398 return parentStepIndex;
401 protected int getContainerStepIndex() {
402 return containerStepIndex;
405 protected int getStepIndex() {
409 private void executeQuery() {
410 String queryString = "g" + Joiner.on("").join(list);
411 Map<String, Object> params = new HashMap<>();
412 if (this.start == null) {
413 params.put("g", source.V());
415 params.put("g", source.V(this.start));
417 this.completeTraversal = this.gremlinGroovy.executeTraversal(queryString, params);
420 public boolean hasNext() {
421 if (this.completeTraversal == null) {
425 return this.completeTraversal.hasNext();
430 if (this.completeTraversal == null) {
434 return (E)this.completeTraversal.next();
438 public List<E> toList() {
439 if (this.completeTraversal == null) {
443 return (List<E>)this.completeTraversal.toList();