You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/03/19 19:26:52 UTC
[34/40] incubator-tinkerpop git commit: the traversal steps provided
by TinkerPop are the foundation for all dsl. GraphTraversal is just a dsl of
traversal. Refactored the process API to reflect this concept. Fixed #592.
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/TreeStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/TreeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/TreeStep.java
deleted file mode 100644
index bead509..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/TreeStep.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map;
-
-import org.apache.tinkerpop.gremlin.process.Path;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
-import org.apache.tinkerpop.gremlin.process.graph.traversal.step.util.ReducingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.graph.util.Tree;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.util.function.TreeSupplier;
-
-import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.BiFunction;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class TreeStep<S> extends ReducingBarrierStep<S, Tree> implements MapReducer, TraversalParent {
-
- private TraversalRing<Object, Object> traversalRing = new TraversalRing<>();
-
- public TreeStep(final Traversal.Admin traversal) {
- super(traversal);
- this.setSeedSupplier((Supplier) TreeSupplier.instance());
- this.setBiFunction(new TreeBiFunction());
- }
-
-
- @Override
- public List<Traversal.Admin<Object, Object>> getLocalChildren() {
- return this.traversalRing.getTraversals();
- }
-
- @Override
- public void addLocalChild(final Traversal.Admin<?, ?> treeTraversal) {
- this.traversalRing.addTraversal(this.integrateChild(treeTraversal));
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return this.getSelfAndChildRequirements(TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS);
- }
-
- @Override
- public MapReduce<MapReduce.NullObject, Tree, MapReduce.NullObject, Tree, Tree> getMapReduce() {
- return TreeMapReduce.instance();
- }
-
- @Override
- public TreeStep<S> clone() {
- final TreeStep<S> clone = (TreeStep<S>) super.clone();
- clone.traversalRing = new TraversalRing<>();
- for (final Traversal.Admin<Object, Object> traversal : this.traversalRing.getTraversals()) {
- clone.traversalRing.addTraversal(clone.integrateChild(traversal.clone()));
- }
- return clone;
- }
-
- @Override
- public Traverser<Tree> processNextStart() {
- if (this.byPass) {
- final Traverser.Admin<S> traverser = this.starts.next();
- return traverser.split(this.reducingBiFunction.apply(new Tree(), traverser), this);
- } else {
- return super.processNextStart();
- }
- }
-
- @Override
- public String toString() {
- return TraversalHelper.makeStepString(this, this.traversalRing);
- }
-
- ///////////
-
- private class TreeBiFunction implements BiFunction<Tree, Traverser<S>, Tree>, Serializable {
-
- private TreeBiFunction() {
-
- }
-
- @Override
- public Tree apply(final Tree mutatingSeed, final Traverser<S> traverser) {
- Tree depth = mutatingSeed;
- final Path path = traverser.path();
- for (int i = 0; i < path.size(); i++) {
- final Object object = TraversalUtil.apply(path.<Object>get(i), TreeStep.this.traversalRing.next());
- if (!depth.containsKey(object))
- depth.put(object, new Tree<>());
- depth = (Tree) depth.get(object);
- }
- TreeStep.this.traversalRing.reset();
- return mutatingSeed;
- }
- }
-
- ///////////
-
- public static final class TreeMapReduce extends StaticMapReduce<MapReduce.NullObject, Tree, MapReduce.NullObject, Tree, Tree> {
-
- private static final TreeMapReduce INSTANCE = new TreeMapReduce();
-
- private TreeMapReduce() {
-
- }
-
- @Override
- public boolean doStage(final Stage stage) {
- return true;
- }
-
- @Override
- public void map(final Vertex vertex, final MapEmitter<NullObject, Tree> emitter) {
- vertex.<TraverserSet<Tree>>property(TraversalVertexProgram.HALTED_TRAVERSERS).ifPresent(traverserSet -> traverserSet.forEach(traverser -> emitter.emit(traverser.get())));
- }
-
- @Override
- public void combine(final NullObject key, final Iterator<Tree> values, final ReduceEmitter<NullObject, Tree> emitter) {
- this.reduce(key, values, emitter);
- }
-
- @Override
- public void reduce(final NullObject key, final Iterator<Tree> values, final ReduceEmitter<NullObject, Tree> emitter) {
- final Tree tree = new Tree();
- values.forEachRemaining(tree::addTree);
- emitter.emit(tree);
- }
-
- @Override
- public Tree generateFinalResult(final Iterator<KeyValue<NullObject, Tree>> keyValues) {
- final Tree tree = new Tree();
- keyValues.forEachRemaining(keyValue -> tree.addTree(keyValue.getValue()));
- return tree;
- }
-
- @Override
- public String getMemoryKey() {
- return REDUCING;
- }
-
- public static final TreeMapReduce instance() {
- return INSTANCE;
- }
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/UnfoldStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/UnfoldStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/UnfoldStep.java
deleted file mode 100644
index e9ec148..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/UnfoldStep.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map;
-
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class UnfoldStep<S, E> extends FlatMapStep<S, E> {
-
- public UnfoldStep(final Traversal.Admin traversal) {
- super(traversal);
- }
-
- @Override
- protected Iterator<E> flatMap(final Traverser.Admin<S> traverser) {
- final S s = traverser.get();
- if (s instanceof Iterator)
- return (Iterator) s;
- else if (s instanceof Iterable)
- return ((Iterable) s).iterator();
- else if (s instanceof Map)
- return ((Map) s).entrySet().iterator();
- else
- return IteratorUtils.of((E) s);
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return Collections.singleton(TraverserRequirement.OBJECT);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/VertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/VertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/VertexStep.java
deleted file mode 100644
index 39dfa47..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/VertexStep.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map;
-
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> {
-
- private final String[] edgeLabels;
- private Direction direction;
- private final Class<E> returnClass;
-
- public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final String... edgeLabels) {
- super(traversal);
- this.direction = direction;
- this.edgeLabels = edgeLabels;
- this.returnClass = returnClass;
- }
-
- @Override
- protected Iterator<E> flatMap(final Traverser.Admin<Vertex> traverser) {
- return Vertex.class.isAssignableFrom(this.returnClass) ?
- (Iterator<E>) traverser.get().vertices(this.direction, this.edgeLabels) :
- (Iterator<E>) traverser.get().edges(this.direction, this.edgeLabels);
- }
-
- public Direction getDirection() {
- return this.direction;
- }
-
- public String[] getEdgeLabels() {
- return this.edgeLabels;
- }
-
- public Class<E> getReturnClass() {
- return this.returnClass;
- }
-
- public void reverseDirection() {
- this.direction = this.direction.opposite();
- }
-
- @Override
- public String toString() {
- return TraversalHelper.makeStepString(this, this.direction, Arrays.asList(this.edgeLabels), this.returnClass.getSimpleName().toLowerCase());
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return Collections.singleton(TraverserRequirement.OBJECT);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Bindings.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Bindings.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Bindings.java
deleted file mode 100644
index 44ff69e..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Bindings.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.function.Function;
-
-/**
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class Bindings<T> {
- private final SortedMap<String, T> map = new TreeMap<>();
-
- public Bindings() {
- }
-
- public Bindings(final Map<String, T> map) {
- this.map.putAll(map);
- }
-
- public Bindings<T> put(final String name, final T value) {
- map.put(name, value);
- return this;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("{");
- boolean first = true;
- for (Map.Entry<String, T> entry : map.entrySet()) {
- if (first) first = false;
- else sb.append(", ");
- sb.append(entry.getKey()).append(':').append(entry.getValue());
- }
- sb.append('}');
- return sb.toString();
- }
-
- public static class BindingsComparator<T> implements Comparator<Bindings<T>> {
- private final Function<T, String> toStringFunction;
-
- public BindingsComparator(Function<T, String> toStringFunction) {
- this.toStringFunction = toStringFunction;
- }
-
- @Override
- public int compare(Bindings<T> left, Bindings<T> right) {
- int cmp = ((Integer) left.map.size()).compareTo(right.map.size());
- if (0 != cmp) return cmp;
-
- Iterator<Map.Entry<String, T>> i1 = left.map.entrySet().iterator();
- Iterator<Map.Entry<String, T>> i2 = right.map.entrySet().iterator();
- while (i1.hasNext()) {
- Map.Entry<String, T> e1 = i1.next();
- Map.Entry<String, T> e2 = i2.next();
-
- cmp = e1.getKey().compareTo(e1.getKey());
- if (0 != cmp) return cmp;
-
- cmp = e1.getValue().toString().compareTo(e2.getValue().toString());
- if (0 != cmp) return cmp;
- }
-
- return 0;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/CrossJoinEnumerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/CrossJoinEnumerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/CrossJoinEnumerator.java
deleted file mode 100644
index 3285eaf..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/CrossJoinEnumerator.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.function.BiConsumer;
-
-/**
- * An Enumerator which finds the Cartesian product of two other Enumerators,
- * expanding at the same rate in either dimension.
- * This maximizes the size of the product with respect to the number of expansions of the base Enumerators.
- */
-public class CrossJoinEnumerator<T> implements Enumerator<T> {
-
- private final Enumerator<T> xEnum, yEnum;
-
- public CrossJoinEnumerator(final Enumerator<T> xEnum,
- final Enumerator<T> yEnum) {
- this.xEnum = xEnum;
- this.yEnum = yEnum;
- }
-
- public int size() {
- return xEnum.size() * yEnum.size();
- }
-
- // note: permits random access
- public boolean visitSolution(final int index,
- final BiConsumer<String, T> visitor) {
- int sq = (int) Math.sqrt(index);
-
- // choose x and y such that the solution represented by index
- // remains constant as this Enumerator expands
- int x, y;
-
- if (0 == index) {
- x = y = 0;
- } else {
- int r = index - sq * sq;
- if (r < sq) {
- x = sq;
- y = r;
- } else {
- x = r - sq;
- y = sq;
- }
- }
-
- // expand x if necessary
- if (!hasIndex(xEnum, sq)) {
- if (0 == xEnum.size()) {
- return false;
- }
-
- x = index % xEnum.size();
- y = index / xEnum.size();
- }
-
- // expand y if necessary
- if (!hasIndex(yEnum, y)) {
- int height = yEnum.size();
- if (0 == height) {
- return false;
- }
-
- x = index / height;
- if (!hasIndex(xEnum, x)) {
- return false;
- }
- y = index % height;
- }
-
- // solutions are visited completely (if we have reached this point), else not at all
- return xEnum.visitSolution(x, visitor) && yEnum.visitSolution(y, visitor);
- }
-
- private boolean hasIndex(final Enumerator<T> e,
- final int index) {
- return index < e.size() || e.visitSolution(index, (BiConsumer<String, T>) MatchStep.TRIVIAL_CONSUMER);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Enumerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Enumerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Enumerator.java
deleted file mode 100644
index 169f76b..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/Enumerator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.function.BiConsumer;
-
-/**
- * An array of key/value maps accessible by index.
- * The total size of the enumerator may be unknown when it is created;
- * it grows when successive solutions are requested, computing as many as necessary.
- *
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public interface Enumerator<T> {
-
- /**
- * @return the number of solutions so far known; the enumerator has at least this many.
- * This should be a relatively cheap operation.
- */
- int size();
-
- /**
- * Provides access to a solution, allowing it to be printed, put into a map, etc.
- *
- * @param index the index of the solution
- * @param visitor a consumer for each key/value pair in the solution
- * @return whether a solution exists at the given index and was visited
- */
- boolean visitSolution(int index, BiConsumer<String, T> visitor);
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/InnerJoinEnumerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/InnerJoinEnumerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/InnerJoinEnumerator.java
deleted file mode 100644
index 6cc3099..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/InnerJoinEnumerator.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiConsumer;
-
-/**
- * An Enumerator which joins the solutions of a base Enumerator according to repeated variables
- * <p/>
- * Note: this Enumerator requires random access to its base Enumerator,
- * as it maintains a list of indices at which valid solutions are found, and visits only those indices.
- *
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class InnerJoinEnumerator<T> implements Enumerator<T> {
- private final Enumerator<T> baseEnumerator;
- private Iterator<Integer> iterator;
- private final List<Integer> joinIndices;
-
- private final Map<String, T> map;
- private final BiConsumer<String, T> joinVisitor;
-
- private int joinCount;
-
- public InnerJoinEnumerator(final Enumerator<T> baseEnumerator,
- final Set<String> joinVariables) {
-
- this.baseEnumerator = baseEnumerator;
- this.joinIndices = new ArrayList<>();
-
- map = new HashMap<>();
- // TODO: allow for more than two instances of a variable
- joinVisitor = (name, newValue) -> {
- if (joinVariables.contains(name)) {
- T value = map.get(name);
- if (null == value) {
- map.put(name, newValue);
- } else if (value.equals(newValue)) {
- joinCount++;
- }
- } else {
- map.put(name, newValue);
- }
- };
-
- iterator = new Iterator<Integer>() {
- private int currentIndex = -1;
-
- {
- advanceToNext();
- }
-
- public boolean hasNext() {
- // there are no calls to this method
- return false;
- }
-
- public Integer next() {
- int tmp = currentIndex;
- advanceToNext();
- return tmp;
- }
-
- private void advanceToNext() {
- while (true) {
- map.clear();
- joinCount = 0;
-
- if (!baseEnumerator.visitSolution(++currentIndex, joinVisitor)) {
- iterator = null;
- return;
- }
-
- if (joinVariables.size() == joinCount) {
- joinIndices.add(currentIndex);
- return;
- }
- }
- }
- };
- }
-
- public int size() {
- return joinIndices.size();
- }
-
- public boolean visitSolution(int i, BiConsumer<String, T> visitor) {
- while (i >= joinIndices.size()) {
- if (null == iterator) {
- return false;
- }
-
- iterator.next();
- }
-
- map.clear();
- if (!baseEnumerator.visitSolution(joinIndices.get(i), joinVisitor)) {
- throw new IllegalStateException();
- }
-
- for (Map.Entry<String, T> entry : map.entrySet()) {
- visitor.accept(entry.getKey(), entry.getValue());
- }
-
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/IteratorEnumerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/IteratorEnumerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/IteratorEnumerator.java
deleted file mode 100644
index f974daf..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/IteratorEnumerator.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.function.BiConsumer;
-
-/**
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class IteratorEnumerator<T> implements Enumerator<T> {
- private final String name;
- private Iterator<T> iterator;
- private final List<T> memory = new ArrayList<>();
-
- public IteratorEnumerator(final String name,
- final Iterator<T> iterator) {
- this.name = name;
- this.iterator = iterator;
- }
-
- public int size() {
- return memory.size();
- }
-
- public boolean visitSolution(final int index,
- final BiConsumer<String, T> visitor) {
- T value;
-
- if (index < memory.size()) {
- value = memory.get(index);
- } else do {
- if (null == iterator) {
- return false;
- } else if (!iterator.hasNext()) {
- // free up memory as soon as possible
- iterator = null;
- return false;
- }
-
- value = iterator.next();
- memory.add(value);
- } while (index >= memory.size());
-
- MatchStep.visit(name, value, visitor);
-
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/MatchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/MatchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/MatchStep.java
deleted file mode 100644
index e51e21d..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/MatchStep.java
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import org.apache.tinkerpop.gremlin.process.FastNoSuchElementException;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.AbstractStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traverser.B_O_PA_S_SE_SL_Traverser;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.Stack;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/**
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public final class MatchStep<S, E> extends AbstractStep<S, Map<String, E>> implements TraversalParent {
-
- static final BiConsumer<String, Object> TRIVIAL_CONSUMER = (s, t) -> {
- };
-
- private static final String ANON_LABEL_PREFIX = "_";
-
- // optimize before processing each start object, by default
- private static final int DEFAULT_STARTS_PER_OPTIMIZE = 1;
-
- private final String startLabel;
- private final Map<String, List<TraversalWrapper<S, S>>> traversalsByStartAs;
- private final List<Traversal> traversals = new ArrayList<>();
-
- private int startsPerOptimize = DEFAULT_STARTS_PER_OPTIMIZE;
- private int optimizeCounter = -1;
- private int anonLabelCounter = 0;
-
- private Enumerator<S> currentSolution;
- private int currentIndex;
-
- // initial value allows MatchStep to be used as a stand-alone query engine
- private Traverser.Admin<S> currentStart;
-
- public MatchStep(final Traversal.Admin traversal, final String startLabel, final Traversal... traversals) {
- super(traversal);
- this.startLabel = startLabel;
- this.traversalsByStartAs = new HashMap<>();
- this.currentStart = new B_O_PA_S_SE_SL_Traverser<>(null, this);
- for (final Traversal tl : traversals) {
- addTraversalPrivate(tl);
- this.integrateChild(tl.asAdmin());
- this.traversals.add(tl);
- }
- checkSolvability();
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return this.getSelfAndChildRequirements();
- }
-
- @Override
- public String toString() {
- return TraversalHelper.makeStepString(this, this.traversalsByStartAs);
- }
-
- /**
- * Adds an individual traversal to an already-constructed MatchStep.
- * The query must be solvable after addition (i.e. should not require the addition of
- * further traversals in order to be solvable)
- * This method should be called before the query is first executed.
- *
- * @param traversal the traversal to add
- */
- public void addTraversal(final Traversal<S, S> traversal) {
- addTraversalPrivate(traversal);
- this.traversals.add(traversal);
- this.integrateChild(traversal.asAdmin());
- checkSolvability();
- }
-
- public void setStartsPerOptimize(final int startsPerOptimize) {
- if (startsPerOptimize < 1) {
- throw new IllegalArgumentException();
- }
- this.startsPerOptimize = startsPerOptimize;
- }
-
- @Override
- protected Traverser<Map<String, E>> processNextStart() throws NoSuchElementException {
- final Map<String, E> map = new HashMap<>();
- final Traverser<Map<String, E>> result = this.currentStart.split(map, this);
- final BiConsumer<String, S> resultSetter = (name, value) -> map.put(name, (E) value);
-
- while (true) { // break out when the current solution is exhausted and there are no more starts
- if (null == this.currentSolution) {
- if (this.starts.hasNext()) {
- this.optimizeCounter = (this.optimizeCounter + 1) % this.startsPerOptimize;
- if (0 == this.optimizeCounter) {
- optimize();
- }
-
- this.currentStart = this.starts.next();
- this.currentSolution = solveFor(IteratorUtils.of(this.currentStart.get()));
- this.currentIndex = 0;
- } else {
- throw FastNoSuchElementException.instance();
- }
- }
-
- map.clear();
- if (this.currentSolution.visitSolution(this.currentIndex++, resultSetter)) {
- return result;
- } else {
- this.currentSolution = null;
- }
- }
- }
-
- /**
- * @return a description of the current state of this step, including the query plan and gathered statistics
- */
- public String summarize() {
- final StringBuilder sb = new StringBuilder("match \"")
- .append(this.startLabel)
- .append("\":\t")
- .append(findCost(this.startLabel))
- .append('\n');
- summarize(this.startLabel, sb, new HashSet<>(), 1);
- return sb.toString();
- }
-
- private void summarize(final String outLabel,
- final StringBuilder sb,
- final Set<String> visited,
- final int indent) {
- if (!visited.contains(outLabel)) {
- visited.add(outLabel);
- final List<TraversalWrapper<S, S>> outs = traversalsByStartAs.get(outLabel);
- if (null != outs) {
- for (final TraversalWrapper<S, S> w : outs) {
- for (int i = 0; i < indent; i++) sb.append('\t');
- sb.append(outLabel).append("->").append(w.endLabel).append(":\t");
- sb.append(findCost(w));
- sb.append('\t').append(w);
- sb.append('\n');
- summarize(w.endLabel, sb, visited, indent + 1);
- }
- }
- }
- }
-
- private void addTraversalPrivate(final Traversal<S, S> traversal) {
-
- String startAs = traversal.asAdmin().getStartStep().getLabel().orElseThrow(()
- -> new IllegalArgumentException("All match traversals must have their start step labeled with as()"));
- String endAs = traversal.asAdmin().getEndStep().getLabel().orElse(null);
- checkAs(startAs);
- if (null == endAs) {
- endAs = createAnonymousAs();
- } else {
- checkAs(endAs);
- }
-
- final TraversalWrapper<S, S> wrapper = new TraversalWrapper<>(traversal, startAs, endAs);
- // index all wrapped traversals by their startLabel
- List<TraversalWrapper<S, S>> l2 = this.traversalsByStartAs.get(startAs);
- if (null == l2) {
- l2 = new LinkedList<>();
- this.traversalsByStartAs.put(startAs, l2);
- }
- l2.add(wrapper);
- }
-
- // given all the wrapped traversals, determine bad patterns in the set and throw exceptions if not solvable
- private void checkSolvability() {
- final Set<String> pathSet = new HashSet<>();
- final Stack<String> stack = new Stack<>();
- stack.push(this.startLabel);
- int countTraversals = 0;
- while (!stack.isEmpty()) {
- final String outAs = stack.peek();
- if (pathSet.contains(outAs)) {
- stack.pop();
- pathSet.remove(outAs);
- } else {
- pathSet.add(outAs);
- final List<TraversalWrapper<S, S>> l = traversalsByStartAs.get(outAs);
- if (null != l) {
- for (final TraversalWrapper<S, S> tw : l) {
- countTraversals++;
- if (pathSet.contains(tw.endLabel)) {
- throw new IllegalArgumentException("The provided traversal set contains a cycle due to '"
- + tw.endLabel + '\'');
- }
- stack.push(tw.endLabel);
- }
- }
- }
- }
-
- int totalTraversals = 0;
- for (List<TraversalWrapper<S, S>> l : this.traversalsByStartAs.values()) {
- totalTraversals += l.size();
- }
-
- if (countTraversals < totalTraversals) {
- throw new IllegalArgumentException("The provided traversal set contains unreachable as-label(s)");
- }
- }
-
- private static void checkAs(final String as) {
- // note: this won't happen so long as the anon prefix is the same as Traversal.UNDERSCORE
- if (isAnonymousAs(as)) {
- throw new IllegalArgumentException("The step named '" + as + "' uses reserved prefix '"
- + ANON_LABEL_PREFIX + '\'');
- }
- }
-
- private static boolean isAnonymousAs(final String as) {
- return as.startsWith(ANON_LABEL_PREFIX);
- }
-
- private String createAnonymousAs() {
- return ANON_LABEL_PREFIX + ++this.anonLabelCounter;
- }
-
- /**
- * Directly applies this match query to a sequence of inputs
- *
- * @param inputs a sequence of inputs
- * @return an enumerator over all solutions
- */
- public Enumerator<S> solveFor(final Iterator<S> inputs) {
- return solveFor(startLabel, inputs);
- }
-
- private Enumerator<S> solveFor(final String localStartAs,
- final Iterator<S> inputs) {
- List<TraversalWrapper<S, S>> outs = traversalsByStartAs.get(localStartAs);
- if (null == outs) {
- // no out-traversals from here; just enumerate the values bound to localStartAs
- return isAnonymousAs(localStartAs)
- ? new SimpleEnumerator<>(localStartAs, inputs)
- : new IteratorEnumerator<>(localStartAs, inputs);
- } else {
- // for each value bound to localStartAs, feed it into all out-traversals in parallel and join the results
- return new SerialEnumerator<>(localStartAs, inputs, o -> {
- Enumerator<S> result = null;
- Set<String> leftLabels = new HashSet<>();
-
- for (TraversalWrapper<S, S> w : outs) {
- TraversalUpdater<S, S> updater
- = new TraversalUpdater<>(w, IteratorUtils.of(o), currentStart, this.getId());
-
- Set<String> rightLabels = new HashSet<>();
- addVariables(w.endLabel, rightLabels);
- Enumerator<S> ie = solveFor(w.endLabel, updater);
- result = null == result ? ie : crossJoin(result, ie, leftLabels, rightLabels);
- leftLabels.addAll(rightLabels);
- }
-
- return result;
- });
- }
- }
-
- private static <T> Enumerator<T> crossJoin(final Enumerator<T> left,
- final Enumerator<T> right,
- final Set<String> leftLabels,
- final Set<String> rightLabels) {
- Set<String> shared = new HashSet<>();
- for (String s : rightLabels) {
- if (leftLabels.contains(s)) {
- shared.add(s);
- }
- }
-
- Enumerator<T> cj = new CrossJoinEnumerator<>(left, right);
- return shared.size() > 0 ? new InnerJoinEnumerator<>(cj, shared) : cj;
- }
-
- // recursively add all non-anonymous variables from a starting point in the query
- private void addVariables(final String localStartAs,
- final Set<String> variables) {
- if (!isAnonymousAs(localStartAs)) {
- variables.add(localStartAs);
- }
-
- List<TraversalWrapper<S, S>> outs = traversalsByStartAs.get(localStartAs);
- if (null != outs) {
- for (TraversalWrapper<S, S> w : outs) {
- String endAs = w.endLabel;
- if (!variables.contains(endAs)) {
- addVariables(endAs, variables);
- }
- }
- }
- }
-
- // applies a visitor, skipping anonymous variables
- static <T> void visit(final String name,
- final T value,
- final BiConsumer<String, T> visitor) {
- if (!isAnonymousAs(name)) {
- visitor.accept(name, value);
- }
- }
-
- /**
- * Computes and applies a new query plan based on gathered statistics about traversal inputs and outputs.
- */
- // note: optimize() is never called from within a solution iterator, as it changes the query plan
- public void optimize() {
- optimizeAt(startLabel);
- }
-
- private void optimizeAt(final String outAs) {
- List<TraversalWrapper<S, S>> outs = traversalsByStartAs.get(outAs);
- if (null != outs) {
- for (TraversalWrapper<S, S> t : outs) {
- optimizeAt(t.endLabel);
- updateOrderingFactor(t);
- }
- Collections.sort(outs);
- }
- }
-
- private double findCost(final TraversalWrapper<S, S> root) {
- double bf = root.findBranchFactor();
- return bf + findCost(root.endLabel, root.findBranchFactor());
- }
-
- private double findCost(final String outAs,
- final double branchFactor) {
- double bf = branchFactor;
-
- double cost = 0;
-
- List<TraversalWrapper<S, S>> outs = traversalsByStartAs.get(outAs);
- if (null != outs) {
- for (TraversalWrapper<S, S> child : outs) {
- cost += bf * findCost(child);
- bf *= child.findBranchFactor();
- }
- }
-
- return cost;
- }
-
- /**
- * @param outLabel the out-label of one or more traversals in the query
- * @return the expected cost, in the current query plan, of applying the branch of the query plan at
- * the given out-label to one start value
- */
- public double findCost(final String outLabel) {
- return findCost(outLabel, 1.0);
- }
-
- private void updateOrderingFactor(final TraversalWrapper<S, S> w) {
- w.orderingFactor = ((w.findBranchFactor() - 1) / findCost(w));
- }
-
- @Override
- public List<Traversal> getLocalChildren() {
- return this.traversals;
- }
-
- /**
- * A wrapper for a traversal in a query which maintains statistics about the traversal as
- * it consumes inputs and produces outputs.
- * The "branch factor" of the traversal is an important factor in determining its place in the query plan.
- */
- // note: input and output counts are never "refreshed".
- // The position of a traversal in a query never changes, although its priority / likelihood of being executed does.
- // Priority in turn affects branch factor.
- // However, with sufficient inputs and optimizations,the branch factor is expected to converge on a stable value.
- public static class TraversalWrapper<A, B> implements Comparable<TraversalWrapper<A, B>> {
- private final Traversal<A, B> traversal;
- private final String startLabel, endLabel;
- private int totalInputs = 0;
- private int totalOutputs = 0;
- private double orderingFactor;
-
- public TraversalWrapper(final Traversal<A, B> traversal,
- final String startLabel,
- final String endLabel) {
- this.traversal = traversal;
- this.startLabel = startLabel;
- this.endLabel = endLabel;
- }
-
- public void incrementInputs() {
- this.totalInputs++;
- }
-
- public void incrementOutputs(int outputs) {
- this.totalOutputs += outputs;
- }
-
- // TODO: take variance into account, to avoid penalizing traversals for early encounters with super-inputs,
- // or simply for never having been tried
- public double findBranchFactor() {
- return 0 == this.totalInputs ? 1 : this.totalOutputs / ((double) this.totalInputs);
- }
-
- @Override
- public int compareTo(final TraversalWrapper<A, B> other) {
- return ((Double) this.orderingFactor).compareTo(other.orderingFactor);
- }
-
- public Traversal<A, B> getTraversal() {
- return this.traversal;
- }
-
- public void reset() {
- this.traversal.asAdmin().reset();
- }
-
- @Override
- public String toString() {
- return this.traversal.toString();
- //return "[" + this.startLabel + "->" + this.endLabel + "," + findBranchFactor() + ","
- // + this.totalInputs + "," + this.totalOutputs + "," + this.traversal + "]";
- }
- }
-
- /**
- * A helper object which wraps a traversal, submitting starts and counting results per start
- */
- public static class TraversalUpdater<A, B> implements Iterator<B> {
- private final TraversalWrapper<A, B> w;
- private int outputs = -1;
-
- public TraversalUpdater(final TraversalWrapper<A, B> w,
- final Iterator<A> inputs,
- final Traverser<A> start,
- final String as) {
- this.w = w;
-
- Iterator<A> seIter = new SideEffectIterator<>(inputs, ignored -> {
- // only increment traversal input and output counts once an input
- // has been completely processed by the traversal
- if (-1 != outputs) {
- w.incrementInputs();
- w.incrementOutputs(outputs);
- }
- outputs = 0;
- });
- Iterator<Traverser<A>> starts = new MapIterator<>(seIter,
- o -> {
- final Traverser.Admin<A> traverser = ((Traverser.Admin<A>) start).split();
- traverser.set((A) o);
- return traverser;
- });
-
- w.reset();
-
- // with the traversal "empty" and ready for re-use, add new starts
- w.traversal.asAdmin().addStarts(starts);
- }
-
- // note: may return true after first returning false (inheriting this behavior from e.g. DefaultTraversal)
- @Override
- public boolean hasNext() {
- return w.traversal.hasNext();
- }
-
- @Override
- public B next() {
- outputs++;
- B b = w.traversal.next();
-
- // immediately check hasNext(), possibly updating the traverser's statistics
- // even if we otherwise abandon the iterator
- w.traversal.hasNext();
-
- return b;
- }
- }
-
- // an iterator which executes a side-effect the first time hasNext() is called before a next()
- private static class SideEffectIterator<T> implements Iterator<T> {
- private final Consumer onHasNext;
- private final Iterator<T> baseIterator;
- private boolean ready = true;
-
- private SideEffectIterator(final Iterator<T> baseIterator,
- final Consumer onHasNext) {
- this.onHasNext = onHasNext;
- this.baseIterator = baseIterator;
- }
-
- @Override
- public boolean hasNext() {
- if (this.ready) {
- this.onHasNext.accept(null);
- this.ready = false;
- }
- return this.baseIterator.hasNext();
- }
-
- @Override
- public T next() {
- T value = this.baseIterator.next();
- this.ready = true;
- return value;
- }
- }
-
- private static class MapIterator<A, B> implements Iterator<B> {
- private final Function<A, B> map;
- private final Iterator<A> baseIterator;
-
- public MapIterator(final Iterator<A> baseIterator, final Function<A, B> map) {
- this.map = map;
- this.baseIterator = baseIterator;
- }
-
- @Override
- public boolean hasNext() {
- return this.baseIterator.hasNext();
- }
-
- @Override
- public B next() {
- return this.map.apply(this.baseIterator.next());
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SerialEnumerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SerialEnumerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SerialEnumerator.java
deleted file mode 100644
index ce0739d..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SerialEnumerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-
-/**
- * An enumerator which consumes values from an iterator and maps each value to a secondary enumerator
- * (for example, a join)
- * Enumerated indices cover all solutions in the secondary enumerators,
- * in ascending order according to the value iterator and the enumerators' own indices.
- *
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class SerialEnumerator<T> implements Enumerator<T> {
- private final String name;
- private Iterator<T> iterator;
- private final Function<T, Enumerator<T>> constructor;
- private final List<Enumerator<T>> memory = new ArrayList<>();
- private final List<T> values = new ArrayList<>();
-
- // TODO: this only assigned, not accessed until the efficient implementation of size() is restored
- private int completedEnumsSize = 0;
-
- public SerialEnumerator(final String name,
- final Iterator<T> iterator,
- final Function<T, Enumerator<T>> constructor) {
- this.name = name;
- this.iterator = iterator;
- this.constructor = constructor;
- }
-
- public int size() {
- // TODO: restore the more efficient implementation of size() while taking into account that
- // traversal iterators such as DefaultTraversal may return hasNext=true after first returning hasNext=false
- /*
- int size = completedEnumsSize;
- if (!sideEffects.isEmpty()) {
- size += sideEffects.get(sideEffects.size() - 1).size();
- }
- return size;
- */
-
- //*
- int size = 0;
- for (Enumerator<T> e : memory) size += e.size();
- return size;
- //*/
- }
-
- // note: *not* intended for random access; use binary search if this is ever needed
- public boolean visitSolution(final int index,
- final BiConsumer<String, T> visitor) {
- int totalSize = 0;
- int memIndex = 0;
- while (true) {
- if (memIndex < memory.size()) {
- Enumerator<T> e = memory.get(memIndex);
-
- if (e.visitSolution(index - totalSize, visitor)) {
- // additionally, bind the value stored in this enumerator
- MatchStep.visit(name, values.get(memIndex), visitor);
-
- return true;
- } else {
- totalSize += e.size();
- memIndex++;
- }
- } else {
- if (null == iterator) {
- return false;
- } else if (!iterator.hasNext()) {
- // free up memory as soon as possible
- iterator = null;
- return false;
- }
-
- if (!memory.isEmpty()) {
- int lastSize = memory.get(memIndex - 1).size();
-
- // first remove the head enumeration if it exists and is empty
- // (only the head will ever be empty, avoiding wasted space)
- if (0 == lastSize) {
- memIndex--;
- memory.remove(memIndex);
- values.remove(memIndex);
- } else {
- completedEnumsSize += lastSize;
- }
- }
-
- T value = iterator.next();
- values.add(value);
- Enumerator<T> e = constructor.apply(value);
- memory.add(memory.size(), e);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SimpleEnumerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SimpleEnumerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SimpleEnumerator.java
deleted file mode 100644
index 37443f4..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/map/match/SimpleEnumerator.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.map.match;
-
-import java.util.Iterator;
-import java.util.function.BiConsumer;
-
-/**
- * An enumerator of at most one element
- *
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class SimpleEnumerator<T> implements Enumerator<T> {
-
- private final String name;
- private Iterator<T> iterator;
- private T element;
-
- public SimpleEnumerator(final String name,
- final Iterator<T> iterator) {
- this.name = name;
- this.iterator = iterator;
- }
-
- @Override
- public int size() {
- return null == element ? 0 : 1;
- }
-
- @Override
- public boolean visitSolution(int index, BiConsumer<String, T> visitor) {
- if (0 != index) {
- return false;
- }
-
- if (null != iterator) {
- if (iterator.hasNext()) {
- element = iterator.next();
- }
- iterator = null;
- }
-
- if (null != element) {
- MatchStep.visit(name, element, visitor);
- return true;
- }
-
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AddPropertyStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AddPropertyStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AddPropertyStep.java
deleted file mode 100644
index e1914dc..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AddPropertyStep.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.structure.Element;
-
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class AddPropertyStep<S extends Element> extends SideEffectStep<S> {
-
- private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT);
-
- private final String key;
- private final Object value;
-
- public AddPropertyStep(final Traversal.Admin traversal, final String key, final Object value) {
- super(traversal);
- this.key = key;
- this.value = value;
- }
-
- @Override
- protected void sideEffect(final Traverser.Admin<S> traverser) {
- traverser.get().property(this.key, this.value);
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return REQUIREMENTS;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AggregateStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AggregateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AggregateStep.java
deleted file mode 100644
index 3c88312..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/AggregateStep.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.VertexTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
-import org.apache.tinkerpop.gremlin.process.graph.traversal.step.SideEffectCapable;
-import org.apache.tinkerpop.gremlin.process.graph.traversal.step.util.CollectingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class AggregateStep<S> extends CollectingBarrierStep<S> implements SideEffectCapable, TraversalParent, MapReducer<MapReduce.NullObject, Object, MapReduce.NullObject, Object, Collection> {
-
- private Traversal.Admin<S, Object> aggregateTraversal = null;
- private String sideEffectKey;
-
- public AggregateStep(final Traversal.Admin traversal, final String sideEffectKey) {
- super(traversal);
- this.sideEffectKey = sideEffectKey;
- this.getTraversal().asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, BulkSetSupplier.instance());
- }
-
- @Override
- public String getSideEffectKey() {
- return this.sideEffectKey;
- }
-
- @Override
- public String toString() {
- return TraversalHelper.makeStepString(this, this.sideEffectKey, this.aggregateTraversal);
- }
-
- @Override
- public MapReduce<MapReduce.NullObject, Object, MapReduce.NullObject, Object, Collection> getMapReduce() {
- return new AggregateMapReduce(this);
- }
-
- @Override
- public void addLocalChild(final Traversal.Admin<?, ?> aggregateTraversal) {
- this.aggregateTraversal = this.integrateChild(aggregateTraversal);
- }
-
- @Override
- public List<Traversal.Admin<S, Object>> getLocalChildren() {
- return null == this.aggregateTraversal ? Collections.emptyList() : Collections.singletonList(this.aggregateTraversal);
- }
-
- @Override
- public void barrierConsumer(final TraverserSet<S> traverserSet) {
- traverserSet.forEach(traverser ->
- TraversalHelper.addToCollection(
- traverser.getSideEffects().get(this.sideEffectKey),
- TraversalUtil.applyNullable(traverser, this.aggregateTraversal),
- traverser.bulk()));
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
- }
-
- @Override
- public AggregateStep<S> clone() {
- final AggregateStep<S> clone = (AggregateStep<S>) super.clone();
- if (null != this.aggregateTraversal)
- clone.aggregateTraversal = clone.integrateChild(this.aggregateTraversal.clone());
- return clone;
- }
-
- ////////
-
- public static final class AggregateMapReduce extends StaticMapReduce<MapReduce.NullObject, Object, MapReduce.NullObject, Object, Collection> {
-
- public static final String AGGREGATE_STEP_SIDE_EFFECT_KEY = "gremlin.aggregateStep.sideEffectKey";
-
- private String sideEffectKey;
- private Supplier<Collection> collectionSupplier;
-
- private AggregateMapReduce() {
-
- }
-
- public AggregateMapReduce(final AggregateStep step) {
- this.sideEffectKey = step.getSideEffectKey();
- this.collectionSupplier = step.getTraversal().asAdmin().getSideEffects().<Collection>getRegisteredSupplier(this.sideEffectKey).orElse(BulkSet::new);
- }
-
- @Override
- public void storeState(final Configuration configuration) {
- super.storeState(configuration);
- configuration.setProperty(AGGREGATE_STEP_SIDE_EFFECT_KEY, this.sideEffectKey);
- }
-
- @Override
- public void loadState(final Configuration configuration) {
- this.sideEffectKey = configuration.getString(AGGREGATE_STEP_SIDE_EFFECT_KEY);
- this.collectionSupplier = TraversalVertexProgram.getTraversalSupplier(configuration).get().getSideEffects().<Collection>getRegisteredSupplier(this.sideEffectKey).orElse(BulkSet::new);
- }
-
- @Override
- public boolean doStage(final Stage stage) {
- return stage.equals(Stage.MAP);
- }
-
- @Override
- public void map(final Vertex vertex, final MapEmitter<NullObject, Object> emitter) {
- VertexTraversalSideEffects.of(vertex).<Collection<?>>orElse(this.sideEffectKey, Collections.emptyList()).forEach(emitter::emit);
- }
-
- @Override
- public Collection generateFinalResult(final Iterator<KeyValue<NullObject, Object>> keyValues) {
- final Collection collection = this.collectionSupplier.get();
- keyValues.forEachRemaining(keyValue -> collection.add(keyValue.getValue()));
- return collection;
- }
-
- @Override
- public String getMemoryKey() {
- return this.sideEffectKey;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GraphStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GraphStep.java
deleted file mode 100644
index e36ea37..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GraphStep.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.TraversalEngine;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.EngineDependent;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class GraphStep<S extends Element> extends StartStep<S> implements EngineDependent {
-
- protected final Class<S> returnClass;
- protected Object[] ids;
- protected transient Supplier<Iterator<S>> iteratorSupplier;
-
- public GraphStep(final Traversal.Admin traversal, final Class<S> returnClass, final Object... ids) {
- super(traversal);
- this.returnClass = returnClass;
- this.ids = ids;
- for (int i = 0; i < this.ids.length; i++) {
- if (this.ids[i] instanceof Element)
- this.ids[i] = ((Element) this.ids[i]).id();
- }
- this.iteratorSupplier = () -> (Iterator<S>) (Vertex.class.isAssignableFrom(this.returnClass) ?
- this.getTraversal().getGraph().get().vertices(this.ids) :
- this.getTraversal().getGraph().get().edges(this.ids));
- }
-
- public String toString() {
- return TraversalHelper.makeStepString(this, Arrays.toString(this.ids), this.returnClass.getSimpleName().toLowerCase());
- }
-
- public boolean returnsVertices() {
- return Vertex.class.isAssignableFrom(this.returnClass);
- }
-
- public boolean returnsEdges() {
- return Edge.class.isAssignableFrom(this.returnClass);
- }
-
- public Class<S> getReturnClass() {
- return this.returnClass;
- }
-
- public void setIteratorSupplier(final Supplier<Iterator<S>> iteratorSupplier) {
- this.iteratorSupplier = iteratorSupplier;
- }
-
- public Object[] getIds() {
- return this.ids;
- }
-
- public void clearIds() {
- this.ids = new Object[0];
- }
-
- @Override
- public void onEngine(final TraversalEngine traversalEngine) {
- if (traversalEngine.isComputer()) {
- this.iteratorSupplier = Collections::emptyIterator;
- }
- }
-
- @Override
- protected Traverser<S> processNextStart() {
- if (this.first)
- this.start = null == this.iteratorSupplier ? EmptyIterator.instance() : this.iteratorSupplier.get();
- return super.processNextStart();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GroupCountSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GroupCountSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GroupCountSideEffectStep.java
deleted file mode 100644
index 997d1db..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/graph/traversal/step/sideEffect/GroupCountSideEffectStep.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.graph.traversal.step.sideEffect;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.VertexTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
-import org.apache.tinkerpop.gremlin.process.graph.traversal.step.SideEffectCapable;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.util.MapHelper;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupCountSideEffectStep<S, E> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, MapReducer<E, Long, E, Long, Map<E, Long>> {
-
- private Traversal.Admin<S, E> groupTraversal = null;
- private String sideEffectKey;
-
- public GroupCountSideEffectStep(final Traversal.Admin traversal, final String sideEffectKey) {
- super(traversal);
- this.sideEffectKey = sideEffectKey;
- this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
- }
-
- @Override
- protected void sideEffect(final Traverser.Admin<S> traverser) {
- final Map<Object, Long> groupCountMap = traverser.sideEffects(this.sideEffectKey);
- MapHelper.incr(groupCountMap, TraversalUtil.applyNullable(traverser.asAdmin(), this.groupTraversal), traverser.bulk());
- }
-
- @Override
- public String getSideEffectKey() {
- return this.sideEffectKey;
- }
-
- @Override
- public MapReduce<E, Long, E, Long, Map<E, Long>> getMapReduce() {
- return new GroupCountSideEffectMapReduce<>(this);
- }
-
- @Override
- public String toString() {
- return TraversalHelper.makeStepString(this, this.sideEffectKey, this.groupTraversal);
- }
-
- @Override
- public void addLocalChild(final Traversal.Admin<?, ?> groupTraversal) {
- this.groupTraversal = this.integrateChild(groupTraversal);
- }
-
- @Override
- public List<Traversal.Admin<S, E>> getLocalChildren() {
- return null == this.groupTraversal ? Collections.emptyList() : Collections.singletonList(this.groupTraversal);
- }
-
- @Override
- public Set<TraverserRequirement> getRequirements() {
- return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
- }
-
- @Override
- public GroupCountSideEffectStep<S, E> clone() {
- final GroupCountSideEffectStep<S, E> clone = (GroupCountSideEffectStep<S, E>) super.clone();
- if (null != this.groupTraversal)
- clone.groupTraversal = clone.integrateChild(this.groupTraversal.clone());
- return clone;
- }
-
- ///////
-
- public static final class GroupCountSideEffectMapReduce<E> extends StaticMapReduce<E, Long, E, Long, Map<E, Long>> {
-
- public static final String GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY = "gremlin.groupCountSideEffectStep.sideEffectKey";
-
- private String sideEffectKey;
- private Supplier<Map<E, Long>> mapSupplier;
-
- private GroupCountSideEffectMapReduce() {
-
- }
-
- public GroupCountSideEffectMapReduce(final GroupCountSideEffectStep step) {
- this.sideEffectKey = step.getSideEffectKey();
- this.mapSupplier = step.getTraversal().asAdmin().getSideEffects().<Map<E, Long>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
- }
-
- @Override
- public void storeState(final Configuration configuration) {
- super.storeState(configuration);
- configuration.setProperty(GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY, this.sideEffectKey);
- }
-
- @Override
- public void loadState(final Configuration configuration) {
- this.sideEffectKey = configuration.getString(GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY);
- this.mapSupplier = TraversalVertexProgram.getTraversalSupplier(configuration).get().getSideEffects().<Map<E, Long>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
- }
-
- @Override
- public boolean doStage(final Stage stage) {
- return true;
- }
-
- @Override
- public void map(final Vertex vertex, final MapEmitter<E, Long> emitter) {
- VertexTraversalSideEffects.of(vertex).<Map<E, Number>>orElse(this.sideEffectKey, Collections.emptyMap()).forEach((k, v) -> emitter.emit(k, v.longValue()));
- }
-
- @Override
- public void reduce(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
- long counter = 0;
- while (values.hasNext()) {
- counter = counter + values.next();
- }
- emitter.emit(key, counter);
- }
-
- @Override
- public void combine(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
- reduce(key, values, emitter);
- }
-
- @Override
- public Map<E, Long> generateFinalResult(final Iterator<KeyValue<E, Long>> keyValues) {
- final Map<E, Long> map = this.mapSupplier.get();
- keyValues.forEachRemaining(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
- return map;
- }
-
- @Override
- public String getMemoryKey() {
- return this.sideEffectKey;
- }
- }
-}