Integrate aai-schema-ingest library into aai-core
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / query / builder / GremlinQueryBuilder.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
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
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20 package org.onap.aai.query.builder;
21
22 import com.google.common.base.Joiner;
23 import com.google.common.collect.ArrayListMultimap;
24 import com.google.common.collect.Multimap;
25
26 import org.apache.tinkerpop.gremlin.process.traversal.Path;
27 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
28 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
29 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
30 import org.apache.tinkerpop.gremlin.structure.Direction;
31 import org.apache.tinkerpop.gremlin.structure.Edge;
32 import org.apache.tinkerpop.gremlin.structure.Vertex;
33 import org.onap.aai.db.props.AAIProperties;
34 import org.onap.aai.exceptions.AAIException;
35 import org.onap.aai.introspection.Introspector;
36 import org.onap.aai.introspection.Loader;
37 import org.onap.aai.restcore.search.GremlinGroovyShellSingleton;
38 import org.onap.aai.schema.enums.ObjectMetadata;
39 import org.onap.aai.edges.EdgeRule;
40 import org.onap.aai.edges.EdgeRuleQuery;
41 import org.onap.aai.edges.enums.EdgeType;
42 import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
43 import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
44
45 import java.util.*;
46
47 /**
48  * The Class GremlinQueryBuilder.
49  */
50 public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
51
52         private GremlinGroovyShellSingleton gremlinGroovy = GremlinGroovyShellSingleton.getInstance();
53         private GraphTraversal<?, ?> completeTraversal = null;
54         protected List<String> list = null;
55
56         /**
57          * Instantiates a new gremlin query builder.
58          *
59          * @param loader the loader
60          */
61         public GremlinQueryBuilder(Loader loader, GraphTraversalSource source) {
62                 super(loader, source);
63                 list = new ArrayList<>();
64         }
65
66         /**
67          * Instantiates a new gremlin query builder.
68          *
69          * @param loader the loader
70          * @param start the start
71          */
72         public GremlinQueryBuilder(Loader loader, GraphTraversalSource source, Vertex start) {
73                 super(loader, source, start);
74                 list = new ArrayList<>();
75         }
76
77         @Override
78         public QueryBuilder<Vertex> exactMatchQuery(Introspector obj) {
79                 // TODO not implemented because this is implementation is no longer used
80                 this.createKeyQuery(obj);
81                 this.createContainerQuery(obj);
82                 return (QueryBuilder<Vertex>) this;
83         }
84
85         /**
86          * @{inheritDoc}
87          */
88         @Override
89         public QueryBuilder<Vertex> getVerticesByProperty(String key, Object value) {
90
91                 String term = "";
92                 if (value != null && !(value instanceof String) ) {
93                         term = value.toString();
94                 } else {
95                         term = "'" + value + "'";
96                 }
97                 list.add(".has('" + key + "', " + term + ")");
98                 stepIndex++;
99                 return (QueryBuilder<Vertex>) this;
100         }
101
102         @Override
103         public QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, Object value) {
104                 boolean bValue = false;
105
106                 if(value instanceof String){
107                         bValue = Boolean.valueOf(value.toString());
108                 } else if(value instanceof Boolean){
109                         bValue = (Boolean) value;
110                 }
111
112                 list.add(".has('" + key + "', " + bValue + ")");
113                 stepIndex++;
114                 return (QueryBuilder<Vertex>) this;
115         }
116
117         /**
118          * @{inheritDoc}
119          */
120         @Override
121         public QueryBuilder<Vertex> getVerticesByProperty(String key, List<?> values) {
122
123                 String predicate = "P.within(#!#argument#!#)";
124                 List<String> arguments = new ArrayList<>();
125                 for (Object item : values) {
126                         if (item != null && !(item instanceof String)) {
127                                 arguments.add(item.toString());
128                         } else {
129                                 arguments.add("'" + item + "'");
130                         }
131                 }
132                 String argument = Joiner.on(",").join(arguments);
133                 predicate = predicate.replace("#!#argument#!#", argument);
134                 list.add(".has('" + key + "', " + predicate + ")");
135                 stepIndex++;
136                 return (QueryBuilder<Vertex>) this;
137         }
138         
139         /**
140      * @{inheritDoc}
141      */
142     @Override
143     public QueryBuilder<Vertex> getVerticesByProperty(String key) {
144
145         list.add(".has('" + key + "')");
146         stepIndex++;
147         return (QueryBuilder<Vertex>) this;
148     }
149     
150     /**
151      * @{inheritDoc}
152      */
153     @Override
154     public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key) {
155
156         String term = "";
157         list.add(".hasNot('" + key + "')");
158         stepIndex++;
159         return (QueryBuilder<Vertex>) this;
160     }
161
162         /**
163          * @{inheritDoc}
164          */
165         @Override
166         public QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value) {
167
168                 String term = "";
169                 String predicate = "org.janusgraph.core.attribute.Text.textPrefix(#!#argument#!#)";
170                 if (value != null && !(value instanceof String) ) {
171                         term = value.toString();
172                 } else {
173                         term = "'" + value + "'";
174                 }
175                 predicate = predicate.replace("#!#argument#!#", term);
176                 list.add(".has('" + key + "', " + predicate + ")");
177                 stepIndex++;
178                 return (QueryBuilder<Vertex>) this;
179         }
180
181         /**
182          * @{inheritDoc}
183          */
184         @Override
185         public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, Object value) {
186
187                 String term = "";
188                 String predicate = "P.neq(#!#argument#!#)";
189                 if (value != null && !(value instanceof String) ) {
190                         term = value.toString();
191                 } else {
192                         term = "'" + value + "'";
193                 }
194                 predicate = predicate.replace("#!#argument#!#", term);
195                 list.add(".has('" + key + "', " + predicate + ")");
196                 stepIndex++;
197                 return (QueryBuilder<Vertex>) this;
198         }
199         
200         /**
201          * @{inheritDoc}
202          */
203         @Override
204         public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key, List<?> values) {
205
206                 String predicate = "P.without(#!#argument#!#)";
207                 List<String> arguments = new ArrayList<>();
208                 for (Object item : values) {
209                         if (item != null && !(item instanceof String)) {
210                                 arguments.add(item.toString());
211                         } else {
212                                 arguments.add("'" + item + "'");
213                         }
214                 }
215                 String argument = Joiner.on(",").join(arguments);
216                 predicate = predicate.replace("#!#argument#!#", argument);
217                 list.add(".has('" + key + "', " + predicate + ")");
218                 stepIndex++;
219                 return (QueryBuilder<Vertex>) this;
220         }
221         
222     @Override
223     public QueryBuilder<Vertex> getVerticesGreaterThanProperty(String key, Object value) {
224         String predicate = "P.gte(#!#argument1#!#)";
225         String term;
226         if (value != null && !(value instanceof String) ) {
227             term = value.toString();
228         } else {
229             term = "'" + value + "'";
230         }
231         predicate = predicate.replace("#!#argument1#!#", term);
232         list.add(".has('" + key + "', " + predicate + ")");
233         stepIndex++;
234         return (QueryBuilder<Vertex>) this;
235     }
236     
237     @Override
238     public QueryBuilder<Vertex> getVerticesLessThanProperty(String key, Object value) {
239         String predicate = "P.lte(#!#argument1#!#)";
240         String term;
241         if (value != null && !(value instanceof String) ) {
242             term = value.toString();
243         } else {
244             term = "'" + value + "'";
245         }
246         predicate = predicate.replace("#!#argument1#!#", term);
247         list.add(".has('" + key + "', " + predicate + ")");
248         stepIndex++;
249         return (QueryBuilder<Vertex>) this;
250     }
251     
252
253
254     
255         /**
256          * @{inheritDoc}
257          */
258         @Override
259         public QueryBuilder<Vertex> getChildVerticesFromParent(String parentKey, String parentValue, String childType) {
260                 /*
261                 String query = ".has('aai-node-type', '" + childType + "')";
262                 
263                 return this.processGremlinQuery(parentKey, parentValue, query);
264                 */
265                 //TODO
266                 return (QueryBuilder<Vertex>) this;
267         }
268         
269         /**
270          * @{inheritDoc}
271          */
272         @Override
273         public QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map) {
274                 
275                 for (Map.Entry<String, String> es : map.entrySet()) {
276                         list.add(".has('" + es.getKey() + "', '" + es.getValue() + "')");
277                         stepIndex++;
278                 }
279                 list.add(".has('aai-node-type', '" + type + "')");
280                 stepIndex++;
281                 return (QueryBuilder<Vertex>) this;
282         }
283         
284         /**
285          * @{inheritDoc}
286          */
287         @Override
288         public QueryBuilder<Vertex> createKeyQuery(Introspector obj) {
289                 Set<String> keys = obj.getKeys();
290
291                 for (String key : keys) {
292                         
293                         this.getVerticesByProperty(key, obj.<Object>getValue(key));
294                         
295                 }               
296                 return (QueryBuilder<Vertex>) this;
297         }
298         
299         /**
300          * @throws NoEdgeRuleFoundException 
301          * @throws AAIException 
302          * @{inheritDoc}
303          */
304         @Override
305         public QueryBuilder createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException {
306                 String parentName = parent.getDbName();
307                 String childName = child.getDbName();
308                 if (parent.isContainer()) {
309                         parentName = parent.getChildDBName();
310                 }
311                 if (child.isContainer()) {
312                         childName = child.getChildDBName();
313                 }
314                 this.edgeQueryToVertex(type, parentName, childName, null);
315                 return this;
316                         
317         }
318
319         @Override
320         public QueryBuilder createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException{
321                 String parentName = parent.getDbName();
322                 String childName = child.getDbName();
323                 if (parent.isContainer()) {
324                         parentName = parent.getChildDBName();
325                 }
326                 if (child.isContainer()) {
327                         childName = child.getChildDBName();
328                 }
329                 this.edgeQueryToVertex(type, parentName, childName, null, true);
330                 return this;
331         }
332
333         /**
334          *
335          * @{inheritDoc}
336          */
337         @Override
338         public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException {
339                 String parentName = out.getDbName();
340                 String childName = in.getDbName();
341                 if (out.isContainer()) {
342                         parentName = out.getChildDBName();
343                 }
344                 if (in.isContainer()) {
345                         childName = in.getChildDBName();
346                 }
347                 this.edgeQueryToVertex(type, parentName, childName, labels);
348                 return (QueryBuilder<Vertex>) this;
349         }
350
351
352         public QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
353                 this.edgeQuery(type, outNodeType, inNodeType, labels);
354                 return (QueryBuilder<Edge>)this;
355         }
356
357         private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels) throws AAIException {
358             this.edgeQueryToVertex(type, outType, inType, labels, false);
359         }
360
361         /**
362          * Edge query.
363          *
364          * @param outType the out type
365          * @param inType the in type
366          * @throws NoEdgeRuleFoundException
367          * @throws AAIException
368          */
369         private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels, boolean isPrivateEdge) throws AAIException {
370                 markParentBoundary();
371                 Multimap<String, EdgeRule> rules = ArrayListMultimap.create();
372                 EdgeRuleQuery.Builder qB = new EdgeRuleQuery.Builder(outType, inType).edgeType(type).setPrivate(isPrivateEdge);
373
374                 try {
375                         if (labels == null) {
376                                 rules.putAll(edgeRules.getRules(qB.build()));
377                         } else {
378                                 for (String label : labels) {
379                                         rules.putAll(edgeRules.getRules(qB.label(label).build()));
380                                 }
381                         }
382                 } catch (EdgeRuleNotFoundException e) {
383                         throw new NoEdgeRuleFoundException(e);
384                 }
385
386                 final List<String> inLabels = new ArrayList<>();
387                 final List<String> outLabels = new ArrayList<>();
388
389                 for (EdgeRule rule : rules.values()) {
390                         if (labels != null && !labels.contains(rule.getLabel())) {
391                                 return;
392                         } else {
393                                 if (Direction.IN.equals(rule.getDirection())) {
394                                         inLabels.add(rule.getLabel());
395                                 } else {
396                                         outLabels.add(rule.getLabel());
397                                 }
398                         }
399                 }
400
401                 if(inLabels.isEmpty() && outLabels.isEmpty()) {
402                         throw new NoEdgeRuleFoundException("no " + type.toString() + " edge rule between " + outType + " and " + inType );
403                 } else if (inLabels.isEmpty() && !outLabels.isEmpty()) {
404                         list.add(".out('" + String.join("','", outLabels) + "')");
405                 } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
406                         list.add(".in('" + String.join("','", inLabels) + "')");
407                 } else {
408                         list.add(".union(__.in('" + String.join("','", inLabels) + "')" + ", __.out('" + String.join("','", outLabels) + "'))");
409                 }
410                 stepIndex++;
411                 list.add(".has('" + AAIProperties.NODE_TYPE + "', '" + inType + "')");
412                 stepIndex++;
413                 
414         }
415         
416         /**
417          * Edge query.
418          *
419          * @param outType the out type
420          * @param inType the in type
421          * @throws NoEdgeRuleFoundException 
422          * @throws AAIException 
423          */
424         private void edgeQuery(EdgeType type, String outType, String inType, List<String> labels) throws AAIException {
425                 markParentBoundary();
426                 Multimap<String, EdgeRule> rules = ArrayListMultimap.create();
427                 EdgeRuleQuery.Builder qB = new EdgeRuleQuery.Builder(outType, inType).edgeType(type);
428                 try {
429                         if (labels == null) {
430                                 rules.putAll(edgeRules.getRules(qB.build()));
431                         } else {
432                                 for (String label : labels) {
433                                         rules.putAll(edgeRules.getRules(qB.label(label).build()));
434                                 }
435                         }
436                 } catch (EdgeRuleNotFoundException e) {
437                         throw new NoEdgeRuleFoundException(e);
438                 }
439                 
440                 final List<String> inLabels = new ArrayList<>();
441                 final List<String> outLabels = new ArrayList<>();
442
443                 for (EdgeRule rule : rules.values()) {
444                         if (labels != null && !labels.contains(rule.getLabel())) {
445                                 return;
446                         } else {
447                                 if (Direction.IN.equals(rule.getDirection())) {
448                                         inLabels.add(rule.getLabel());
449                                 } else {
450                                         outLabels.add(rule.getLabel());
451                                 }
452                         }
453                 }
454
455                 if(inLabels.isEmpty() && outLabels.isEmpty()) {
456                         throw new NoEdgeRuleFoundException("no " + type.toString() + " edge rule between " + outType + " and " + inType );
457                 } else if (inLabels.isEmpty() && !outLabels.isEmpty()) {
458                         list.add(".outE('" + String.join("','", outLabels) + "')");
459                 } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
460                         list.add(".inE('" + String.join("','", inLabels) + "')");
461                 } else {
462                         list.add(".union(__.inE('" + String.join("','", inLabels) + "')" + ", __.outE('" + String.join("','", outLabels) + "'))");
463                 }
464                 
465                 stepIndex++;
466                 
467         }
468         @Override
469         public QueryBuilder<E> limit(long amount) {
470                 list.add(".limit(" + amount + ")");
471                 return this;
472         }
473         /**
474          * @{inheritDoc}
475          */
476         @Override
477         public QueryBuilder<Vertex> createContainerQuery(Introspector obj) {
478                 String type = obj.getChildDBName();
479                 String abstractType = obj.getMetadata(ObjectMetadata.ABSTRACT);
480                 if (abstractType != null) {
481                         String[] inheritors = obj.getMetadata(ObjectMetadata.INHERITORS).split(",");
482                         String[] wrapped = new String[inheritors.length];
483                         StringBuilder command = new StringBuilder();
484                         command.append("P.within(");
485                         for (int i = 0; i < inheritors.length; i++) {
486                                 wrapped[i] = "'" + inheritors[i] + "'";
487                         }
488                         command.append(Joiner.on(",").join(wrapped));
489                         command.append(")");
490                         list.add(".has('aai-node-type', " + command + ")");
491                         
492                 } else {
493                         list.add(".has('aai-node-type', '" + type + "')");
494                 }
495                 stepIndex++;
496                 this.markContainer();
497                 return (QueryBuilder<Vertex>) this;
498         }
499         
500         @Override
501         public QueryBuilder<E> union(QueryBuilder<E>... builder) {
502                 markParentBoundary();
503                 String[] traversals = new String[builder.length];
504                 StringBuilder command = new StringBuilder();
505                 for (int i = 0; i < builder.length; i++) {
506                         traversals[i] = "__" + builder[i].getQuery();
507                 }
508                 command.append(".union(");
509                 command.append(Joiner.on(",").join(traversals));
510                 command.append(")");
511                 list.add(command.toString());
512                 stepIndex++;
513                 
514                 return this;
515         }
516         
517         @Override
518         public QueryBuilder<E> where(QueryBuilder<E>... builder) {
519                 markParentBoundary();
520                 List<String> traversals = new ArrayList<>();
521                 for (int i = 0; i < builder.length; i++) {
522                         traversals.add(".where(__" + builder[i].getQuery() + ")");
523                         stepIndex++;
524                 }
525                 list.addAll(traversals);
526                 
527                 
528                 return this;
529         }
530
531         @Override
532         public QueryBuilder<E> or(QueryBuilder<E>... builder) {
533                 markParentBoundary();
534                 String[] traversals = new String[builder.length];
535                 StringBuilder command = new StringBuilder();
536                 for (int i = 0; i < builder.length; i++) {
537                         traversals[i] = "__" + builder[i].getQuery();
538                 }
539                 command.append(".or(");
540                 command.append(Joiner.on(",").join(traversals));
541                 command.append(")");
542                 list.add(command.toString());
543                 stepIndex++;
544
545                 return this;
546         }
547         
548         @Override
549         public QueryBuilder<E> store(String name) {
550                 this.list.add(".store('"+ name + "')");
551                 stepIndex++;
552                 
553                 return this;
554         }
555         
556         @Override
557         public QueryBuilder<E> cap(String name) {
558                 this.list.add(".cap('"+ name + "')");
559                 stepIndex++;
560                 
561                 return this;
562         }
563         
564         @Override
565         public QueryBuilder<E> unfold() {
566                 this.list.add(".unfold()");
567                 stepIndex++;
568                 
569                 return this;
570         }
571         
572         @Override
573         public QueryBuilder<E> dedup() {
574                 this.list.add(".dedup()");
575                 stepIndex++;
576                 
577                 return this;
578         }
579         
580         @Override
581         public QueryBuilder<E> emit() {
582                 this.list.add(".emit()");
583                 stepIndex++;
584                 
585                 return this;
586         }
587         
588         @Override
589         public QueryBuilder<E> repeat(QueryBuilder<E> builder) {
590                 this.list.add(".repeat(__" + builder.getQuery()  + ")");
591                 stepIndex++;
592                 
593                 return this;
594         }
595         
596         @Override
597         public QueryBuilder<E> until(QueryBuilder<E> builder) {
598                 this.list.add(".until(__" + builder.getQuery() + ")");
599                 stepIndex++;
600                 
601                 return this;
602         }
603         
604         @Override
605         public QueryBuilder<E> groupCount() {
606                 this.list.add(".groupCount()");
607                 stepIndex++;
608                 
609                 return this;
610         }
611         
612         @Override
613         public QueryBuilder<E> both() {
614                 this.list.add(".both()");
615                 stepIndex++;
616                 
617                 return this;
618         }
619         
620         @Override
621         public QueryBuilder<Tree> tree() {
622                 this.list.add(".tree()");
623                 stepIndex++;
624                 
625                 return (QueryBuilder<Tree>)this;
626         }
627         
628         @Override
629         public QueryBuilder<E> by(String name) {
630                 this.list.add(".by('"+ name + "')");
631                 stepIndex++;
632                 
633                 return this;
634         }
635         
636         /**
637          * {@inheritDoc}
638          */
639         @Override
640         public QueryBuilder<E> simplePath(){
641                 this.list.add(".simplePath()");
642                 stepIndex++;
643                 return this;
644         }
645
646         /**
647          * {@inheritDoc}
648          */
649         @Override
650         public QueryBuilder<Path> path(){
651                 this.list.add(".path()");
652                 stepIndex++;
653                 return (QueryBuilder<Path>)this;
654         }
655         
656         @Override
657         public QueryBuilder<Edge> outE() {
658                 this.list.add(".outE()");
659                 stepIndex++;
660                 
661                 return (QueryBuilder<Edge>)this;
662         }
663         
664         @Override
665         public QueryBuilder<Edge> inE() {
666                 this.list.add(".inE()");
667                 stepIndex++;
668                 
669                 return (QueryBuilder<Edge>)this;
670         }
671         
672         @Override
673         public QueryBuilder<Vertex> outV() {
674                 this.list.add(".outV()");
675                 stepIndex++;
676                 
677                 return (QueryBuilder<Vertex>)this;
678         }
679         
680         @Override
681         public QueryBuilder<Vertex> inV() {
682                 this.list.add(".inV()");
683                 stepIndex++;
684                 
685                 return (QueryBuilder<Vertex>)this;
686         }
687         
688         @Override
689         public QueryBuilder<E> not(QueryBuilder<E> builder) {
690                 this.list.add(".not(" + "__" + builder.getQuery() + ")");
691                 stepIndex++;
692                 
693                 return this;
694         }
695         
696         @Override
697         public QueryBuilder<E> as(String name) {
698                 this.list.add(".as('" + name + "')");
699                 stepIndex++;
700                 
701                 return this;
702         }
703         
704         @Override
705         public QueryBuilder<E> select(String name) {
706                 this.list.add(".select('" + name + "')");
707                 stepIndex++;
708                 
709                 return this;
710         }
711         /**
712          * @{inheritDoc}
713          */
714         @Override
715         public QueryBuilder<E> getParentQuery() {
716                 return cloneQueryAtStep(parentStepIndex);
717         }
718         
719         @Override
720         public QueryBuilder<E> getContainerQuery() {
721                 return cloneQueryAtStep(containerStepIndex);
722         }
723         
724         /**
725          * @{inheritDoc}
726          */
727         @Override
728         public <T2> T2 getQuery() {
729                 StringBuilder sb = new StringBuilder();
730                 
731                 for (String piece : this.list) {
732                         sb.append(piece);
733                 }
734                 
735                 return (T2)sb.toString();
736         }
737         
738         /**
739          * @{inheritDoc}
740          */
741         @Override
742         public void markParentBoundary() {
743                 parentStepIndex = stepIndex;
744         }
745         
746         @Override
747         public void markContainer() {
748                 this.containerStepIndex = stepIndex;
749         }
750         
751         /**
752          * @{inheritDoc}
753          */
754         @Override
755         public Vertex getStart() {
756                 return this.start;
757         }
758
759         protected int getParentStepIndex() {
760                 return parentStepIndex;
761         }
762
763         protected int getContainerStepIndex() {
764                 return containerStepIndex;
765         }
766
767         protected int getStepIndex() {
768                 return stepIndex;
769         }
770         
771         private void executeQuery() {
772                 String queryString = "g" + Joiner.on("").join(list);
773                 Map<String, Object> params = new HashMap<>();
774                 if (this.start == null) {
775                         params.put("g", source.V());
776                 } else {
777                         params.put("g", source.V(this.start));
778                 }
779                 this.completeTraversal = this.gremlinGroovy.executeTraversal(queryString, params);
780         }
781         @Override
782         public boolean hasNext() {
783                 if (this.completeTraversal == null) {
784                         executeQuery();
785                 }
786                 
787                 return this.completeTraversal.hasNext();
788         }
789         
790         @Override
791         public E next() {
792                 if (this.completeTraversal == null) {
793                         executeQuery();
794                 }
795                 
796                 return (E)this.completeTraversal.next();
797         }
798         
799         @Override
800         public List<E> toList() {
801                 if (this.completeTraversal == null) {
802                         executeQuery();
803                 }
804                 
805                 return (List<E>)this.completeTraversal.toList();
806         }
807
808         protected QueryBuilder<Edge> has(String key, String value) {
809                 this.list.add(".has('" + key + "','" + value + "')");
810
811                 return (QueryBuilder<Edge>)this;
812         }
813         
814 }