Update tinkerpop to 3.2.3 in aai-core
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / query / builder / GremlinQueryBuilder.java
index 2cc78f4..e68cfe6 100644 (file)
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.onap.aai.query.builder;
 
 import com.google.common.base.Joiner;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
 
+import java.util.*;
+
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -33,18 +36,18 @@ import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.onap.aai.db.props.AAIProperties;
-import org.onap.aai.exceptions.AAIException;
-import org.onap.aai.introspection.Introspector;
-import org.onap.aai.introspection.Loader;
-import org.onap.aai.restcore.search.GremlinGroovyShellSingleton;
-import org.onap.aai.schema.enums.ObjectMetadata;
 import org.onap.aai.edges.EdgeRule;
 import org.onap.aai.edges.EdgeRuleQuery;
 import org.onap.aai.edges.enums.EdgeType;
 import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.introspection.Introspector;
+import org.onap.aai.introspection.Loader;
+import org.onap.aai.restcore.search.GremlinGroovyShell;
+import org.onap.aai.schema.enums.ObjectMetadata;
 import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
-
-import java.util.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The Class GremlinQueryBuilder.
@@ -53,10 +56,14 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
 
     private static final String ARGUMENT2 = "#!#argument#!#";
     private static final String HAS = ".has('";
-    private GremlinGroovyShellSingleton gremlinGroovy = GremlinGroovyShellSingleton.getInstance();
+    private static final String SINGLE_QUOTE = "'";
+    private static final String ESCAPE_SINGLE_QUOTE = "\\\'";
+    private GremlinGroovyShell gremlinGroovy = new GremlinGroovyShell();
     private GraphTraversal<?, ?> completeTraversal = null;
     protected List<String> list = null;
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(QueryBuilder.class);
+
     /**
      * Instantiates a new gremlin query builder.
      *
@@ -86,6 +93,22 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         return (QueryBuilder<Vertex>) this;
     }
 
+    @Override
+    protected void vertexHas(String key, Object value) {
+        list.add(HAS + key + "', " + value + ")");
+    }
+
+    @Override
+    protected void vertexHasNot(String key) {
+        list.add(".hasNot('" + key + "')");
+
+    }
+
+    @Override
+    protected void vertexHas(String key) {
+        list.add(HAS + key + "')");
+    }
+
     /**
      * @{inheritDoc}
      */
@@ -93,28 +116,54 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
     public QueryBuilder<Vertex> getVerticesByProperty(String key, Object value) {
 
         String term = "";
-        if (value != null && !(value instanceof String) ) {
+        if (value != null && !(value instanceof String)) {
+            String valueString = value.toString();
+
+            if (valueString.indexOf('\'') != -1) {
+                value = valueString.replace(SINGLE_QUOTE, ESCAPE_SINGLE_QUOTE);
+            }
+            LOGGER.trace("Inside getVerticesByProperty(): key = {}, value = {}", key, value);
             term = value.toString();
+        } else if (value != null && value instanceof String) {
+            String valueString = value.toString();
+
+            if (valueString.indexOf('\'') != -1) {
+                value = valueString.replace(SINGLE_QUOTE, ESCAPE_SINGLE_QUOTE);
+            }
+            LOGGER.trace("Inside getVerticesByProperty(): key = {}, value = {}", key, value);
+            term = "'" + value + "'";
         } else {
             term = "'" + value + "'";
         }
-        list.add(HAS + key + "', " + term + ")");
+        this.vertexHas(key, term);
+        stepIndex++;
+        return (QueryBuilder<Vertex>) this;
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    @Override
+    public QueryBuilder<Vertex> getVerticesByNumberProperty(String key, Object value) {
+        this.vertexHas(key, value);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
 
     @Override
     public QueryBuilder<Vertex> getVerticesByBooleanProperty(String key, Object value) {
-        boolean bValue = false;
 
-        if(value instanceof String){
-            bValue = Boolean.valueOf(value.toString());
-        } else if(value instanceof Boolean){
-            bValue = (Boolean) value;
-        }
+        if (value != null && !"".equals(value)) {
+            boolean bValue = false;
+            if (value instanceof String) {
+                bValue = Boolean.valueOf(value.toString());
+            } else if (value instanceof Boolean) {
+                bValue = (Boolean) value;
+            }
 
-        list.add(HAS + key + "', " + bValue + ")");
-        stepIndex++;
+            this.vertexHas(key, bValue);
+            stepIndex++;
+        }
         return (QueryBuilder<Vertex>) this;
     }
 
@@ -135,29 +184,49 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         }
         String argument = Joiner.on(",").join(arguments);
         predicate = predicate.replace(ARGUMENT2, argument);
-        list.add(HAS + key + "', " + predicate + ")");
+        this.vertexHas(key, predicate);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     /**
      * @{inheritDoc}
      */
     @Override
-    public QueryBuilder<Vertex> getVerticesByProperty(String key) {
+    public QueryBuilder<Vertex> getVerticesByCommaSeperatedValue(String key, String value) {
+        ArrayList<String> arguments = new ArrayList<>(Arrays.asList(value.split(",")));
+        // add the single quotes
+        for (int i = 0; i < arguments.size(); i++) {
+            if (arguments.get(i) != null && !arguments.get(i).startsWith("'") && !arguments.get(i).endsWith("'")) {
+                arguments.set(i, "'" + arguments.get(i).trim() + "'");
+            } else {
+                arguments.set(i, arguments.get(i).trim());
+            }
+        }
+        String predicate = "P.within(#!#argument#!#)";
+        String argument = Joiner.on(",").join(arguments);
+        predicate = predicate.replace(ARGUMENT2, argument);
+        this.vertexHas(key, predicate);
+        stepIndex++;
+        return (QueryBuilder<Vertex>) this;
+    }
 
-        list.add(HAS + key + "')");
+    /**
+     * @{inheritDoc}
+     */
+    @Override
+    public QueryBuilder<Vertex> getVerticesByProperty(String key) {
+        this.vertexHas(key);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     /**
      * @{inheritDoc}
      */
     @Override
     public QueryBuilder<Vertex> getVerticesExcludeByProperty(String key) {
-
-        list.add(".hasNot('" + key + "')");
+        this.vertexHasNot(key);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
@@ -167,16 +236,15 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
      */
     @Override
     public QueryBuilder<Vertex> getVerticesStartsWithProperty(String key, Object value) {
-
         String term = "";
         String predicate = "org.janusgraph.core.attribute.Text.textPrefix(#!#argument#!#)";
-        if (value != null && !(value instanceof String) ) {
+        if (value != null && !(value instanceof String)) {
             term = value.toString();
         } else {
             term = "'" + value + "'";
         }
         predicate = predicate.replace(ARGUMENT2, term);
-        list.add(HAS + key + "', " + predicate + ")");
+        this.vertexHas(key, predicate);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
@@ -189,17 +257,17 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
 
         String term = "";
         String predicate = "P.neq(#!#argument#!#)";
-        if (value != null && !(value instanceof String) ) {
+        if (value != null && !(value instanceof String)) {
             term = value.toString();
         } else {
             term = "'" + value + "'";
         }
         predicate = predicate.replace(ARGUMENT2, term);
-        list.add(HAS + key + "', " + predicate + ")");
+        this.vertexHas(key, predicate);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     /**
      * @{inheritDoc}
      */
@@ -217,60 +285,58 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         }
         String argument = Joiner.on(",").join(arguments);
         predicate = predicate.replace(ARGUMENT2, argument);
-        list.add(HAS + key + "', " + predicate + ")");
+        this.vertexHas(key, predicate);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     @Override
     public QueryBuilder<Vertex> getVerticesGreaterThanProperty(String key, Object value) {
         String predicate = "P.gte(#!#argument1#!#)";
         String term;
-        if (value != null && !(value instanceof String) ) {
+        if (value != null && !(value instanceof String)) {
             term = value.toString();
         } else {
             term = "'" + value + "'";
         }
         predicate = predicate.replace("#!#argument1#!#", term);
-        list.add(HAS + key + "', " + predicate + ")");
+        this.vertexHas(key, predicate);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     @Override
     public QueryBuilder<Vertex> getVerticesLessThanProperty(String key, Object value) {
         String predicate = "P.lte(#!#argument1#!#)";
         String term;
-        if (value != null && !(value instanceof String) ) {
+        if (value != null && !(value instanceof String)) {
             term = value.toString();
         } else {
             term = "'" + value + "'";
         }
         predicate = predicate.replace("#!#argument1#!#", term);
-        list.add(HAS + key + "', " + predicate + ")");
+        this.vertexHas(key, predicate);
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
-
 
-    
     /**
      * @{inheritDoc}
      */
     @Override
     public QueryBuilder<Vertex> getChildVerticesFromParent(String parentKey, String parentValue, String childType) {
-        //TODO
+        // TODO
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     /**
      * @{inheritDoc}
      */
     @Override
     public QueryBuilder<Vertex> getTypedVerticesByMap(String type, Map<String, String> map) {
-        
+
         for (Map.Entry<String, String> es : map.entrySet()) {
+            // TODO what is this and where is it used - need to check
             list.add(HAS + es.getKey() + "', '" + es.getValue() + "')");
             stepIndex++;
         }
@@ -278,7 +344,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         stepIndex++;
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     /**
      * @{inheritDoc}
      */
@@ -287,20 +353,21 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         Set<String> keys = obj.getKeys();
 
         for (String key : keys) {
-            
+
             this.getVerticesByProperty(key, obj.<Object>getValue(key));
-            
-        }        
+
+        }
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     /**
-     * @throws NoEdgeRuleFoundException 
-     * @throws AAIException 
+     * @throws NoEdgeRuleFoundException
+     * @throws AAIException
      * @{inheritDoc}
      */
     @Override
-    public QueryBuilder createEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException {
+    public QueryBuilder createEdgeTraversal(EdgeType type, Introspector parent, Introspector child)
+            throws AAIException {
         String parentName = parent.getDbName();
         String childName = child.getDbName();
         if (parent.isContainer()) {
@@ -311,11 +378,12 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         }
         this.edgeQueryToVertex(type, parentName, childName, null);
         return this;
-            
+
     }
 
     @Override
-    public QueryBuilder createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child) throws AAIException{
+    public QueryBuilder createPrivateEdgeTraversal(EdgeType type, Introspector parent, Introspector child)
+            throws AAIException {
         String parentName = parent.getDbName();
         String childName = child.getDbName();
         if (parent.isContainer()) {
@@ -333,7 +401,8 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
      * @{inheritDoc}
      */
     @Override
-    public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in, List<String> labels) throws AAIException {
+    public QueryBuilder<Vertex> createEdgeTraversalWithLabels(EdgeType type, Introspector out, Introspector in,
+            List<String> labels) throws AAIException {
         String parentName = out.getDbName();
         String childName = in.getDbName();
         if (out.isContainer()) {
@@ -346,13 +415,14 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         return (QueryBuilder<Vertex>) this;
     }
 
-
-    public QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType, List<String> labels) throws AAIException {
+    public QueryBuilder<Edge> getEdgesBetweenWithLabels(EdgeType type, String outNodeType, String inNodeType,
+            List<String> labels) throws AAIException {
         this.edgeQuery(type, outNodeType, inNodeType, labels);
-        return (QueryBuilder<Edge>)this;
+        return (QueryBuilder<Edge>) this;
     }
 
-    private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels) throws AAIException {
+    private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels)
+            throws AAIException {
         this.edgeQueryToVertex(type, outType, inType, labels, false);
     }
 
@@ -364,7 +434,8 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
      * @throws NoEdgeRuleFoundException
      * @throws AAIException
      */
-    private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels, boolean isPrivateEdge) throws AAIException {
+    private void edgeQueryToVertex(EdgeType type, String outType, String inType, List<String> labels,
+            boolean isPrivateEdge) throws AAIException {
         markParentBoundary();
         Multimap<String, EdgeRule> rules = ArrayListMultimap.create();
         EdgeRuleQuery.Builder qB = new EdgeRuleQuery.Builder(outType, inType).edgeType(type).setPrivate(isPrivateEdge);
@@ -390,34 +461,42 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
             } else {
                 if (Direction.IN.equals(rule.getDirection())) {
                     inLabels.add(rule.getLabel());
+                    if (inType.equals(outType)) {// code to handle when a type edges to itself, to add both in and out
+                        outLabels.add(rule.getLabel());
+                    }
                 } else {
                     outLabels.add(rule.getLabel());
+                    if (inType.equals(outType)) {// code to handle when a type edges to itself, to add both in and out
+                        inLabels.add(rule.getLabel());
+                    }
                 }
             }
         }
 
-        if(inLabels.isEmpty() && outLabels.isEmpty()) {
-            throw new NoEdgeRuleFoundException("no " + type.toString() + " edge rule between " + outType + " and " + inType );
+        if (inLabels.isEmpty() && outLabels.isEmpty()) {
+            throw new NoEdgeRuleFoundException(
+                    "no " + type.toString() + " edge rule between " + outType + " and " + inType);
         } else if (inLabels.isEmpty() && !outLabels.isEmpty()) {
             list.add(".out('" + String.join("','", outLabels) + "')");
         } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
             list.add(".in('" + String.join("','", inLabels) + "')");
         } else {
-            list.add(".union(__.in('" + String.join("','", inLabels) + "')" + ", __.out('" + String.join("','", outLabels) + "'))");
+            list.add(".union(__.in('" + String.join("','", inLabels) + "')" + ", __.out('"
+                    + String.join("','", outLabels) + "'))");
         }
         stepIndex++;
         list.add(HAS + AAIProperties.NODE_TYPE + "', '" + inType + "')");
         stepIndex++;
-        
+
     }
-    
+
     /**
      * Edge query.
      *
      * @param outType the out type
      * @param inType the in type
-     * @throws NoEdgeRuleFoundException 
-     * @throws AAIException 
+     * @throws NoEdgeRuleFoundException
+     * @throws AAIException
      */
     private void edgeQuery(EdgeType type, String outType, String inType, List<String> labels) throws AAIException {
         markParentBoundary();
@@ -434,7 +513,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         } catch (EdgeRuleNotFoundException e) {
             throw new NoEdgeRuleFoundException(e);
         }
-        
+
         final List<String> inLabels = new ArrayList<>();
         final List<String> outLabels = new ArrayList<>();
 
@@ -450,24 +529,28 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
             }
         }
 
-        if(inLabels.isEmpty() && outLabels.isEmpty()) {
-            throw new NoEdgeRuleFoundException("no " + type.toString() + " edge rule between " + outType + " and " + inType );
+        if (inLabels.isEmpty() && outLabels.isEmpty()) {
+            throw new NoEdgeRuleFoundException(
+                    "no " + type.toString() + " edge rule between " + outType + " and " + inType);
         } else if (inLabels.isEmpty() && !outLabels.isEmpty()) {
             list.add(".outE('" + String.join("','", outLabels) + "')");
         } else if (outLabels.isEmpty() && !inLabels.isEmpty()) {
             list.add(".inE('" + String.join("','", inLabels) + "')");
         } else {
-            list.add(".union(__.inE('" + String.join("','", inLabels) + "')" + ", __.outE('" + String.join("','", outLabels) + "'))");
+            list.add(".union(__.inE('" + String.join("','", inLabels) + "')" + ", __.outE('"
+                    + String.join("','", outLabels) + "'))");
         }
-        
+
         stepIndex++;
-        
+
     }
+
     @Override
     public QueryBuilder<E> limit(long amount) {
         list.add(".limit(" + amount + ")");
         return this;
     }
+
     /**
      * @{inheritDoc}
      */
@@ -486,15 +569,15 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
             command.append(Joiner.on(",").join(wrapped));
             command.append(")");
             list.add(".has('aai-node-type', " + command + ")");
-            
+
         } else {
             list.add(".has('aai-node-type', '" + type + "')");
         }
         stepIndex++;
-        this.markContainer();
+        this.markContainerIndex();
         return (QueryBuilder<Vertex>) this;
     }
-    
+
     @Override
     public QueryBuilder<E> union(QueryBuilder<E>... builder) {
         markParentBoundary();
@@ -508,10 +591,10 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         command.append(")");
         list.add(command.toString());
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> where(QueryBuilder<E>... builder) {
         markParentBoundary();
@@ -521,8 +604,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
             stepIndex++;
         }
         list.addAll(traversals);
-        
-        
+
         return this;
     }
 
@@ -542,100 +624,138 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
 
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> store(String name) {
-        this.list.add(".store('"+ name + "')");
+        this.list.add(".store('" + name + "')");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> cap(String name) {
-        this.list.add(".cap('"+ name + "')");
+        this.list.add(".cap('" + name + "')");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> unfold() {
         this.list.add(".unfold()");
         stepIndex++;
-        
+
         return this;
     }
-    
+
+    @Override
+    public QueryBuilder<E> fold() {
+        this.list.add(".fold()");
+        stepIndex++;
+        return this;
+    }
+
+    @Override
+    public QueryBuilder<E> id() {
+        this.list.add(".id()");
+        stepIndex++;
+        return this;
+    }
+
     @Override
     public QueryBuilder<E> dedup() {
         this.list.add(".dedup()");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> emit() {
         this.list.add(".emit()");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> repeat(QueryBuilder<E> builder) {
-        this.list.add(".repeat(__" + builder.getQuery()  + ")");
+        this.list.add(".repeat(__" + builder.getQuery() + ")");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> until(QueryBuilder<E> builder) {
         this.list.add(".until(__" + builder.getQuery() + ")");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> groupCount() {
         this.list.add(".groupCount()");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> both() {
         this.list.add(".both()");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<Tree> tree() {
         this.list.add(".tree()");
         stepIndex++;
-        
-        return (QueryBuilder<Tree>)this;
+
+        return (QueryBuilder<Tree>) this;
     }
-    
+
     @Override
     public QueryBuilder<E> by(String name) {
-        this.list.add(".by('"+ name + "')");
+        this.list.add(".by('" + name + "')");
         stepIndex++;
-        
+
         return this;
     }
-    
+
+    @Override
+    public QueryBuilder<E> valueMap() {
+        this.list.add(".valueMap()");
+        stepIndex++;
+
+        return this;
+    }
+
+    @Override
+    public QueryBuilder<E> valueMap(String... names) {
+        String stepString = ".valueMap('";
+        for (int i = 0; i < names.length; i++) {
+            stepString = stepString + names[i] + "'";
+            if (i != (names.length - 1)) {
+                stepString = stepString + ",'";
+            }
+        }
+        stepString = stepString + ")";
+        this.list.add(stepString);
+        stepIndex++;
+
+        return this;
+    }
+
     /**
      * {@inheritDoc}
      */
     @Override
-    public QueryBuilder<E> simplePath(){
+    public QueryBuilder<E> simplePath() {
         this.list.add(".simplePath()");
         stepIndex++;
         return this;
@@ -645,67 +765,84 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
      * {@inheritDoc}
      */
     @Override
-    public QueryBuilder<Path> path(){
+    public QueryBuilder<Path> path() {
         this.list.add(".path()");
         stepIndex++;
-        return (QueryBuilder<Path>)this;
+        return (QueryBuilder<Path>) this;
     }
-    
+
     @Override
     public QueryBuilder<Edge> outE() {
         this.list.add(".outE()");
         stepIndex++;
-        
-        return (QueryBuilder<Edge>)this;
+
+        return (QueryBuilder<Edge>) this;
     }
-    
+
     @Override
     public QueryBuilder<Edge> inE() {
         this.list.add(".inE()");
         stepIndex++;
-        
-        return (QueryBuilder<Edge>)this;
+
+        return (QueryBuilder<Edge>) this;
     }
-    
+
     @Override
     public QueryBuilder<Vertex> outV() {
         this.list.add(".outV()");
         stepIndex++;
-        
-        return (QueryBuilder<Vertex>)this;
+
+        return (QueryBuilder<Vertex>) this;
     }
-    
+
     @Override
     public QueryBuilder<Vertex> inV() {
         this.list.add(".inV()");
         stepIndex++;
-        
-        return (QueryBuilder<Vertex>)this;
+
+        return (QueryBuilder<Vertex>) this;
     }
-    
+
     @Override
     public QueryBuilder<E> not(QueryBuilder<E> builder) {
         this.list.add(".not(" + "__" + builder.getQuery() + ")");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> as(String name) {
         this.list.add(".as('" + name + "')");
         stepIndex++;
-        
+
         return this;
     }
-    
+
     @Override
     public QueryBuilder<E> select(String name) {
         this.list.add(".select('" + name + "')");
         stepIndex++;
-        
+
         return this;
     }
+
+    @Override
+    public QueryBuilder<E> select(String... names) {
+        String stepString = ".select('";
+        for (int i = 0; i < names.length; i++) {
+            stepString = stepString + names[i] + "'";
+            if (i != (names.length - 1)) {
+                stepString = stepString + ",'";
+            }
+        }
+        stepString = stepString + ")";
+        this.list.add(stepString);
+        stepIndex++;
+
+        return this;
+    }
+
     /**
      * @{inheritDoc}
      */
@@ -713,26 +850,26 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
     public QueryBuilder<E> getParentQuery() {
         return cloneQueryAtStep(parentStepIndex);
     }
-    
+
     @Override
     public QueryBuilder<E> getContainerQuery() {
         return cloneQueryAtStep(containerStepIndex);
     }
-    
+
     /**
      * @{inheritDoc}
      */
     @Override
     public <T2> T2 getQuery() {
         StringBuilder sb = new StringBuilder();
-        
+
         for (String piece : this.list) {
             sb.append(piece);
         }
-        
-        return (T2)sb.toString();
+
+        return (T2) sb.toString();
     }
-    
+
     /**
      * @{inheritDoc}
      */
@@ -740,12 +877,12 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
     public void markParentBoundary() {
         parentStepIndex = stepIndex;
     }
-    
+
     @Override
-    public void markContainer() {
+    public void markContainerIndex() {
         this.containerStepIndex = stepIndex;
     }
-    
+
     /**
      * @{inheritDoc}
      */
@@ -765,7 +902,7 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
     protected int getStepIndex() {
         return stepIndex;
     }
-    
+
     private void executeQuery() {
         String queryString = "g" + Joiner.on("").join(list);
         Map<String, Object> params = new HashMap<>();
@@ -776,37 +913,42 @@ public abstract class GremlinQueryBuilder<E> extends QueryBuilder<E> {
         }
         this.completeTraversal = this.gremlinGroovy.executeTraversal(queryString, params);
     }
+
     @Override
     public boolean hasNext() {
         if (this.completeTraversal == null) {
             executeQuery();
         }
-        
+
         return this.completeTraversal.hasNext();
     }
-    
+
     @Override
     public E next() {
         if (this.completeTraversal == null) {
             executeQuery();
         }
-        
-        return (E)this.completeTraversal.next();
+
+        return (E) this.completeTraversal.next();
     }
-    
+
     @Override
     public List<E> toList() {
         if (this.completeTraversal == null) {
             executeQuery();
         }
-        
-        return (List<E>)this.completeTraversal.toList();
+
+        return (List<E>) this.completeTraversal.toList();
     }
 
     protected QueryBuilder<Edge> has(String key, String value) {
         this.list.add(HAS + key + "','" + value + "')");
 
-        return (QueryBuilder<Edge>)this;
+        return (QueryBuilder<Edge>) this;
     }
-    
+
+    /*
+     * This is required for the subgraphstrategies to work
+     */
+
 }