This is an automated email from the ASF dual-hosted git repository. okram pushed a commit to branch tp4 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/tp4 by this push: new 37e596a Compilations can now be compared and cloned -- equals, clone, hashcode. This entailed clone, equals, and hashcode for Arguments and CFunctions. We can now cache Compilations as well as split them apart for processors that want to thread components. 37e596a is described below commit 37e596a972a446ec4211b7fece432f9a717c383c Author: Marko A. Rodriguez <okramma...@gmail.com> AuthorDate: Wed Mar 27 12:30:17 2019 -0600 Compilations can now be compared and cloned -- equals, clone, hashcode. This entailed clone, equals, and hashcode for Arguments and CFunctions. We can now cache Compilations as well as split them apart for processors that want to thread components. --- .../tinkerpop/machine/bytecode/BytecodeUtil.java | 4 +- .../machine/bytecode/compiler/Argument.java | 4 +- .../bytecode/compiler/BytecodeArgument.java | 23 +++++++- .../machine/bytecode/compiler/Compilation.java | 13 +++-- .../bytecode/compiler/CompilationCircle.java | 29 +++++++++- .../bytecode/compiler/ConstantArgument.java | 20 +++++++ .../machine/bytecode/compiler/MethodArgument.java | 17 ++++++ .../bytecode/compiler/SourceCompilation.java | 15 ++++++ .../machine/function/AbstractFunction.java | 24 +++++++++ .../tinkerpop/machine/function/CFunction.java | 7 +-- .../machine/function/branch/BranchBranch.java | 27 +++++++++- .../machine/function/branch/RepeatBranch.java | 35 +++++++++--- .../machine/function/filter/FilterFilter.java | 34 +++++++++--- .../machine/function/filter/HasKeyFilter.java | 23 +++++++- .../machine/function/filter/HasKeyValueFilter.java | 28 ++++++++-- .../machine/function/filter/IsFilter.java | 24 +++++++-- .../machine/function/flatmap/FlatMapFlatMap.java | 22 +++++++- .../machine/function/initial/InitialInitial.java | 14 ++++- .../machine/function/map/ConstantMap.java | 12 +++++ .../tinkerpop/machine/function/map/MapMap.java | 23 ++++++-- .../tinkerpop/machine/function/map/PathMap.java | 23 +++++++- .../tinkerpop/machine/function/map/ValueMap.java | 23 ++++++-- .../machine/function/reduce/GroupCountReduce.java | 22 +++++++- .../machine/bytecode/compiler/CompilationTest.java | 62 ++++++++++++++++++++++ 24 files changed, 476 insertions(+), 52 deletions(-) diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java index aa6bca6..5272ce7 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/BytecodeUtil.java @@ -19,7 +19,9 @@ package org.apache.tinkerpop.machine.bytecode; import org.apache.tinkerpop.machine.bytecode.compiler.BytecodeCompiler; +import org.apache.tinkerpop.machine.bytecode.compiler.CommonCompiler; import org.apache.tinkerpop.machine.bytecode.compiler.CompositeCompiler; +import org.apache.tinkerpop.machine.bytecode.compiler.CoreCompiler; import org.apache.tinkerpop.machine.bytecode.compiler.CoreCompiler.Symbols; import org.apache.tinkerpop.machine.coefficient.Coefficient; import org.apache.tinkerpop.machine.processor.ProcessorFactory; @@ -86,7 +88,7 @@ public final class BytecodeUtil { final List<BytecodeCompiler> compilers = new ArrayList<>(); BytecodeUtil.getProcessorFactory(bytecode).ifPresent(f -> compilers.addAll(f.getCompilers())); BytecodeUtil.getStructureFactory(bytecode).ifPresent(f -> compilers.addAll(f.getCompilers())); - return CompositeCompiler.create(compilers); + return CompositeCompiler.create(compilers.isEmpty() ? List.of(CoreCompiler.instance(), CommonCompiler.instance()) : compilers); } public static <C> Optional<Coefficient<C>> getCoefficient(final Bytecode<C> bytecode) { diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Argument.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Argument.java index 495d9a2..f55edc0 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Argument.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Argument.java @@ -27,7 +27,7 @@ import java.util.Arrays; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public interface Argument<E> extends Serializable { +public interface Argument<E> extends Serializable, Cloneable { public <C, S> E mapArg(final Traverser<C, S> traverser); @@ -42,4 +42,6 @@ public interface Argument<E> extends Serializable { return new ConstantArgument<>((E) args[0]); } + public Argument<E> clone(); + } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeArgument.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeArgument.java index 5711ab5..eb2dbaf 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeArgument.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/BytecodeArgument.java @@ -26,7 +26,7 @@ import org.apache.tinkerpop.machine.traverser.Traverser; */ public class BytecodeArgument<E> implements Argument<E> { - private final Compilation compilation; + private Compilation compilation; public BytecodeArgument(final Bytecode arg) { this.compilation = Compilation.compile(arg); @@ -43,6 +43,27 @@ public class BytecodeArgument<E> implements Argument<E> { } @Override + public int hashCode() { + return this.compilation.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof BytecodeArgument && this.compilation.equals(((BytecodeArgument) object).compilation); + } + + @Override + public BytecodeArgument<E> clone() { + try { + final BytecodeArgument<E> clone = (BytecodeArgument<E>) super.clone(); + clone.compilation = this.compilation.clone(); + return clone; + } catch (final CloneNotSupportedException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override public String toString() { return this.compilation.toString(); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java index 9b15d95..0571a03 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/Compilation.java @@ -21,6 +21,7 @@ package org.apache.tinkerpop.machine.bytecode.compiler; import org.apache.tinkerpop.machine.bytecode.Bytecode; import org.apache.tinkerpop.machine.bytecode.BytecodeUtil; import org.apache.tinkerpop.machine.function.CFunction; +import org.apache.tinkerpop.machine.processor.EmptyProcessor; import org.apache.tinkerpop.machine.processor.Processor; import org.apache.tinkerpop.machine.processor.ProcessorFactory; import org.apache.tinkerpop.machine.structure.EmptyStructure; @@ -29,6 +30,7 @@ import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.traverser.TraverserFactory; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -36,9 +38,9 @@ import java.util.List; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public final class Compilation<C, S, E> implements Serializable { +public final class Compilation<C, S, E> implements Serializable, Cloneable { - private final List<CFunction<C>> functions; + private List<CFunction<C>> functions; private final StructureFactory structureFactory; private final ProcessorFactory processorFactory; private final TraverserFactory<C> traverserFactory; @@ -47,7 +49,7 @@ public final class Compilation<C, S, E> implements Serializable { public Compilation(final Bytecode<C> bytecode) { BytecodeUtil.strategize(bytecode); this.structureFactory = BytecodeUtil.getStructureFactory(bytecode).orElse(EmptyStructure.instance()); - this.processorFactory = BytecodeUtil.getProcessorFactory(bytecode).get(); + this.processorFactory = BytecodeUtil.getProcessorFactory(bytecode).orElse(EmptyProcessor.instance()); this.traverserFactory = BytecodeUtil.getTraverserFactory(bytecode).get(); this.functions = BytecodeUtil.getCompilers(bytecode).compile(bytecode); } @@ -148,7 +150,10 @@ public final class Compilation<C, S, E> implements Serializable { try { final Compilation<C, S, E> clone = (Compilation<C, S, E>) super.clone(); clone.processor = null; - // clone.functions = ... we need to do a deep clone given the nested compilations + clone.functions = new ArrayList<>(this.functions.size()); + for (final CFunction<C> function : this.functions) { + clone.functions.add(function.clone()); + } return clone; } catch (final CloneNotSupportedException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationCircle.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationCircle.java index 831ba14..94f8e95 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationCircle.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationCircle.java @@ -19,14 +19,15 @@ package org.apache.tinkerpop.machine.bytecode.compiler; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public final class CompilationCircle<C, S, E> implements Serializable { +public final class CompilationCircle<C, S, E> implements Serializable, Cloneable { - private final List<Compilation<C, S, E>> compilations; + private List<Compilation<C, S, E>> compilations; private final boolean hasCompilations; private int currentCompilation = -1; @@ -53,7 +54,31 @@ public final class CompilationCircle<C, S, E> implements Serializable { } @Override + public int hashCode() { + return this.compilations.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof CompilationCircle && this.compilations.equals(((CompilationCircle) object).compilations); + } + + @Override public String toString() { return this.compilations.toString(); } + + @Override + public CompilationCircle<C, S, E> clone() { + try { + final CompilationCircle<C, S, E> clone = (CompilationCircle<C, S, E>) super.clone(); + clone.compilations = new ArrayList<>(this.compilations.size()); + for (final Compilation<C, S, E> compilation : this.compilations) { + clone.compilations.add(compilation.clone()); + } + return clone; + } catch (final CloneNotSupportedException e) { + throw new RuntimeException(e.getMessage(), e); + } + } } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/ConstantArgument.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/ConstantArgument.java index ecc9b9d..967d4f1 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/ConstantArgument.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/ConstantArgument.java @@ -40,4 +40,24 @@ public class ConstantArgument<E> implements Argument<E> { public <C, S> boolean filterArg(final Traverser<C, S> traverser) { return (Boolean) this.constant; } + + @Override + public ConstantArgument<E> clone() { + return this; + } + + @Override + public int hashCode() { + return this.constant.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof ConstantArgument && this.constant.equals(((ConstantArgument) object).constant); + } + + @Override + public String toString() { + return this.constant.toString(); + } } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/MethodArgument.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/MethodArgument.java index e940ad4..eb985d0 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/MethodArgument.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/MethodArgument.java @@ -65,6 +65,23 @@ public class MethodArgument<E> implements Argument<E> { } @Override + public int hashCode() { + return this.method.hashCode() ^ Arrays.hashCode(this.arguments); + } + + @Override + public boolean equals(final Object object) { + return object instanceof MethodArgument && + this.method.equals(((MethodArgument) object).method) && + Arrays.equals(this.arguments, ((MethodArgument) object).arguments); + } + + @Override + public MethodArgument<E> clone() { + return this; + } + + @Override public String toString() { return this.method + "(" + Arrays.toString(this.arguments) + ")"; } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java index 4b03ce9..70a9603 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/bytecode/compiler/SourceCompilation.java @@ -67,4 +67,19 @@ public final class SourceCompilation<C> { return this.originalSource; } + @Override + public int hashCode() { + return this.originalSource.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof SourceCompilation && this.originalSource.equals(((SourceCompilation) object).originalSource); + } + + @Override + public String toString() { + return this.originalSource.getSourceInstructions().toString(); + } + } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/AbstractFunction.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/AbstractFunction.java index dfb6f8d..97c6bd1 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/AbstractFunction.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/AbstractFunction.java @@ -48,4 +48,28 @@ public abstract class AbstractFunction<C> implements CFunction<C> { public String toString() { return StringFactory.makeFunctionString(this); } + + @Override + public int hashCode() { + return this.coefficient.hashCode() ^ (null == this.label ? 1 : this.label.hashCode()); + } + + @Override + public boolean equals(final Object object) { + return object instanceof AbstractFunction && + this.coefficient.equals(((AbstractFunction) object).coefficient) && + ((null == this.label && null == ((AbstractFunction) object).label) || + (null != this.label && this.label.equals(((AbstractFunction) object).label))); + } + + @Override + public AbstractFunction<C> clone() { + try { + final AbstractFunction<C> clone = (AbstractFunction<C>) super.clone(); + clone.coefficient = this.coefficient.clone(); // TODO: make ImmutableCoefficient? + return clone; + } catch (final CloneNotSupportedException e) { + throw new RuntimeException(e.getMessage(), e); + } + } } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/CFunction.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/CFunction.java index 4f5ee31..38a7d37 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/CFunction.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/CFunction.java @@ -21,17 +21,18 @@ package org.apache.tinkerpop.machine.function; import org.apache.tinkerpop.machine.coefficient.Coefficient; import java.io.Serializable; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public interface CFunction<C> extends Serializable { +public interface CFunction<C> extends Serializable, Cloneable { public Coefficient<C> coefficient(); public String label(); - // TODO: reset() -- some functions do have state that needs resetting. E.g. nested compilation functions. + public CFunction<C> clone(); + // TODO: reset() -- some functions do have state that needs resetting. E.g. nested compilation functions. + // most internal compilations reset() the compilation on every traverser insert. Except branch compilations. } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/BranchBranch.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/BranchBranch.java index af9c126..fbf86e3 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/BranchBranch.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/BranchBranch.java @@ -29,14 +29,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class BranchBranch<C, S, E> extends AbstractFunction<C> implements BranchFunction<C, S, E> { - private final Map<Compilation<C, S, ?>, List<Compilation<C, S, E>>> branches; + private Map<Compilation<C, S, ?>, List<Compilation<C, S, E>>> branches; private BranchBranch(final Coefficient<C> coefficient, final String label, final Map<Compilation<C, S, ?>, List<Compilation<C, S, E>>> branches) { super(coefficient, label); @@ -48,6 +47,30 @@ public final class BranchBranch<C, S, E> extends AbstractFunction<C> implements return this.branches; } + @Override + public int hashCode() { + return super.hashCode() ^ this.branches.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof BranchBranch && this.branches.equals(((BranchBranch) object).branches) && super.equals(object); + } + + @Override + public BranchBranch<C, S, E> clone() { + final BranchBranch<C, S, E> clone = (BranchBranch<C, S, E>) super.clone(); + clone.branches = new HashMap<>(this.branches.size()); + for (final Map.Entry<Compilation<C, S, ?>, List<Compilation<C, S, E>>> entry : this.branches.entrySet()) { + final List<Compilation<C, S, E>> compilations = new ArrayList<>(entry.getValue().size()); + for (final Compilation<C, S, E> compilation : entry.getValue()) { + compilations.add(compilation.clone()); + } + clone.branches.put(entry.getKey().clone(), compilations); + } + return clone; + } + public static <C, S, E> BranchBranch<C, S, E> compile(final Instruction<C> instruction) { final Object[] args = instruction.args(); final Map<Compilation<C, S, ?>, List<Compilation<C, S, E>>> branches = new HashMap<>(); diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java index c13fd69..b496666 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/branch/RepeatBranch.java @@ -28,17 +28,13 @@ import org.apache.tinkerpop.machine.processor.LoopsProcessor; import org.apache.tinkerpop.machine.util.StringFactory; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class RepeatBranch<C, S> extends AbstractFunction<C> { - private final Map<Character, Compilation<C, S, S>> compilations; // TODO: remove private Compilation<C, S, S> repeatCompilation; private Compilation<C, S, ?> untilCompilation; private Compilation<C, S, ?> emitCompilation; @@ -50,7 +46,6 @@ public final class RepeatBranch<C, S> extends AbstractFunction<C> { public RepeatBranch(final Coefficient<C> coefficient, final String label, final List<Object> arguments) { super(coefficient, label); int location = 1; - this.compilations = new LinkedHashMap<>(); for (int i = 0; i < arguments.size(); i = i + 2) { final Character type = (Character) arguments.get(i); if ('e' == type) { @@ -71,14 +66,12 @@ public final class RepeatBranch<C, S> extends AbstractFunction<C> { this.repeatCompilation = (Compilation<C, S, S>) arguments.get(i + 1); location = 3; } - - this.compilations.put((Character) arguments.get(i), (Compilation<C, S, S>) arguments.get(i + 1)); } } @Override public String toString() { - return StringFactory.makeFunctionString(this, this.compilations); + return StringFactory.makeFunctionString(this, repeatCompilation, untilCompilation, emitCompilation); // todo: this is random } public Compilation<C, S, S> getRepeat() { @@ -109,6 +102,32 @@ public final class RepeatBranch<C, S> extends AbstractFunction<C> { return this.hasEndPredicates; } + @Override + public int hashCode() { + return super.hashCode() ^ this.repeatCompilation.hashCode() ^ this.emitCompilation.hashCode() ^ this.untilCompilation.hashCode() ^ + this.emitLocation ^ this.untilLocation; + } + + @Override + public boolean equals(final Object object) { + return object instanceof RepeatBranch && + this.repeatCompilation.equals(((RepeatBranch) object).repeatCompilation) && + this.emitCompilation.equals(((RepeatBranch) object).emitCompilation) && + this.untilCompilation.equals(((RepeatBranch) object).untilCompilation) && + this.emitLocation == ((RepeatBranch) object).emitLocation && + this.untilLocation == ((RepeatBranch) object).untilLocation && + super.equals(object); + } + + @Override + public RepeatBranch<C, S> clone() { + final RepeatBranch<C, S> clone = (RepeatBranch<C, S>) super.clone(); + clone.repeatCompilation = this.repeatCompilation.clone(); + clone.emitCompilation = this.emitCompilation.clone(); + clone.untilCompilation = this.untilCompilation.clone(); + return clone; + } + public static <C, S> RepeatBranch<C, S> compile(final Instruction<C> instruction) { final List<Object> objects = new ArrayList<>(); for (final Object arg : instruction.args()) { diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/FilterFilter.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/FilterFilter.java index 90820cd..fd7a68c 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/FilterFilter.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/FilterFilter.java @@ -27,28 +27,39 @@ import org.apache.tinkerpop.machine.function.FilterFunction; import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.util.StringFactory; -import java.util.Set; - /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class FilterFilter<C, S> extends AbstractFunction<C> implements FilterFunction<C, S> { - private final Pred pred; - private final Argument<S> argument; + private final Pred predicate; + private Argument<S> argument; - private FilterFilter(final Coefficient<C> coefficient, final String label, final Pred pred, final Argument<S> argument) { + private FilterFilter(final Coefficient<C> coefficient, final String label, final Pred predicate, final Argument<S> argument) { super(coefficient, label); - this.pred = pred; + this.predicate = predicate; this.argument = argument; } @Override public boolean test(final Traverser<C, S> traverser) { - return null == this.pred ? + return null == this.predicate ? this.argument.filterArg(traverser) : - this.pred.test(traverser.object(), this.argument.mapArg(traverser)); + this.predicate.test(traverser.object(), this.argument.mapArg(traverser)); + } + + @Override + public int hashCode() { + return super.hashCode() ^ this.predicate.hashCode() ^ this.argument.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof FilterFilter && + this.predicate.equals(((FilterFilter) object).predicate) && + this.argument.equals(((FilterFilter) object).argument) && + super.equals(object); } @Override @@ -56,6 +67,13 @@ public final class FilterFilter<C, S> extends AbstractFunction<C> implements Fil return StringFactory.makeFunctionString(this, this.argument); } + @Override + public FilterFilter<C, S> clone() { + final FilterFilter<C, S> clone = (FilterFilter<C, S>) super.clone(); + clone.argument = this.argument.clone(); + return clone; + } + public static <C, S> FilterFilter<C, S> compile(final Instruction<C> instruction) { final boolean oneArg = instruction.args().length == 1; return new FilterFilter<>(instruction.coefficient(), instruction.label(), diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java index 2dbefe4..17c4e13 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyFilter.java @@ -29,7 +29,6 @@ import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.util.StringFactory; import java.util.Iterator; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -37,7 +36,7 @@ import java.util.Set; public final class HasKeyFilter<C, K, V> extends AbstractFunction<C> implements FilterFunction<C, TMap<K, V>> { private final Pred predicate; - private final Argument<K> key; + private Argument<K> key; private HasKeyFilter(final Coefficient<C> coefficient, final String label, final Pred predicate, final Argument<K> key) { super(coefficient, label); @@ -62,10 +61,30 @@ public final class HasKeyFilter<C, K, V> extends AbstractFunction<C> implements } @Override + public int hashCode() { + return super.hashCode() ^ this.predicate.hashCode() ^ this.key.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof HasKeyFilter && + this.predicate.equals(((HasKeyFilter) object).predicate) && + this.key.equals(((HasKeyFilter) object).key) && + super.equals(object); + } + + @Override public String toString() { return StringFactory.makeFunctionString(this, this.key); } + @Override + public HasKeyFilter<C, K, V> clone() { + final HasKeyFilter<C, K, V> clone = (HasKeyFilter<C, K, V>) super.clone(); + clone.key = this.key.clone(); + return clone; + } + public static <C, K, V> HasKeyFilter<C, K, V> compile(final Instruction<C> instruction) { return new HasKeyFilter<>(instruction.coefficient(), instruction.label(), Pred.valueOf(instruction.args()[0]), Argument.create(instruction.args()[1])); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java index a97a182..c300af3 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/HasKeyValueFilter.java @@ -27,15 +27,13 @@ import org.apache.tinkerpop.machine.structure.data.TMap; import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.util.StringFactory; -import java.util.Set; - /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class HasKeyValueFilter<C, K, V> extends AbstractFunction<C> implements FilterFunction<C, TMap<K, V>> { - private final Argument<K> key; - private final Argument<V> value; + private Argument<K> key; + private Argument<V> value; private HasKeyValueFilter(final Coefficient<C> coefficient, final String label, final Argument<K> key, final Argument<V> value) { super(coefficient, label); @@ -50,10 +48,32 @@ public final class HasKeyValueFilter<C, K, V> extends AbstractFunction<C> implem } @Override + public int hashCode() { + return super.hashCode() ^ this.key.hashCode() ^ this.value.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof HasKeyValueFilter && + this.key.equals(((HasKeyValueFilter) object).key) && + this.value.equals(((HasKeyValueFilter) object).value) && + super.equals(object); + } + + @Override public String toString() { return StringFactory.makeFunctionString(this, this.key, this.value); } + + @Override + public HasKeyValueFilter<C, K, V> clone() { + final HasKeyValueFilter<C, K, V> clone = (HasKeyValueFilter<C, K, V>) super.clone(); + clone.key = this.key.clone(); + clone.value = this.value.clone(); + return clone; + } + public static <C, K, V> HasKeyValueFilter<C, K, V> compile(final Instruction<C> instruction) { return new HasKeyValueFilter<>(instruction.coefficient(), instruction.label(), Argument.create(instruction.args()[0]), Argument.create(instruction.args()[1])); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java index e9bb748..e8549b8 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/filter/IsFilter.java @@ -27,15 +27,13 @@ import org.apache.tinkerpop.machine.function.FilterFunction; import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.util.StringFactory; -import java.util.Set; - /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class IsFilter<C, S> extends AbstractFunction<C> implements FilterFunction<C, S> { private final Pred predicate; - private final Argument<S> argument; + private Argument<S> argument; private IsFilter(final Coefficient<C> coefficient, final String label, final Pred predicate, final Argument<S> argument) { super(coefficient, label); @@ -49,10 +47,30 @@ public final class IsFilter<C, S> extends AbstractFunction<C> implements FilterF } @Override + public int hashCode() { + return super.hashCode() ^ this.predicate.hashCode() ^ this.argument.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof IsFilter && + this.predicate.equals(((IsFilter) object).predicate) && + this.argument.equals(((IsFilter) object).argument) && + super.equals(object); + } + + @Override public String toString() { return StringFactory.makeFunctionString(this, this.predicate, this.argument); } + @Override + public IsFilter<C, S> clone() { + final IsFilter<C, S> clone = (IsFilter<C, S>) super.clone(); + clone.argument = this.argument.clone(); + return clone; + } + public static <C, S> IsFilter<C, S> compile(final Instruction<C> instruction) { return new IsFilter<>(instruction.coefficient(), instruction.label(), Pred.valueOf(instruction.args()[0]), Argument.create(instruction.args()[1])); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/FlatMapFlatMap.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/FlatMapFlatMap.java index c89825f..47a84cd 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/FlatMapFlatMap.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/flatmap/FlatMapFlatMap.java @@ -30,14 +30,13 @@ import org.apache.tinkerpop.machine.util.IteratorUtils; import java.lang.reflect.Array; import java.util.Iterator; import java.util.Map; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class FlatMapFlatMap<C, S, E> extends AbstractFunction<C> implements FlatMapFunction<C, S, E> { - private final Argument<E> argument; + private Argument<E> argument; private FlatMapFlatMap(final Coefficient<C> coefficient, final String label, final Argument<E> argument) { super(coefficient, label); @@ -71,6 +70,25 @@ public final class FlatMapFlatMap<C, S, E> extends AbstractFunction<C> implement } } + @Override + public int hashCode() { + return super.hashCode() ^ this.argument.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof FlatMapFlatMap && + this.argument.equals(((FlatMapFlatMap) object).argument) && + super.equals(object); + } + + @Override + public FlatMapFlatMap<C, S, E> clone() { + final FlatMapFlatMap<C, S, E> clone = (FlatMapFlatMap<C, S, E>) super.clone(); + clone.argument = this.argument.clone(); + return clone; + } + public static <C, S, E> FlatMapFlatMap<C, S, E> compile(final Instruction<C> instruction) { return new FlatMapFlatMap<>(instruction.coefficient(), instruction.label(), Argument.create(instruction.args())); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/InitialInitial.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/InitialInitial.java index e8c490a..601e81f 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/InitialInitial.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/initial/InitialInitial.java @@ -25,8 +25,8 @@ import org.apache.tinkerpop.machine.function.InitialFunction; import org.apache.tinkerpop.machine.util.ArrayIterator; import org.apache.tinkerpop.machine.util.StringFactory; +import java.util.Arrays; import java.util.Iterator; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -46,6 +46,18 @@ public final class InitialInitial<C, S> extends AbstractFunction<C> implements I } @Override + public int hashCode() { + return super.hashCode() ^ Arrays.hashCode(this.objects); + } + + @Override + public boolean equals(final Object object) { + return object instanceof InitialInitial && + Arrays.equals(this.objects, ((InitialInitial) object).objects) && + super.equals(object); + } + + @Override public String toString() { return StringFactory.makeFunctionString(this, this.objects); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ConstantMap.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ConstantMap.java index a5a87aa..bd26b5c 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ConstantMap.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ConstantMap.java @@ -43,6 +43,18 @@ public final class ConstantMap<C, S, E> extends AbstractFunction<C> implements M } @Override + public int hashCode() { + return super.hashCode() ^ this.constant.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof ConstantMap && + this.constant.equals(((ConstantMap) object).constant) && + super.equals(object); + } + + @Override public String toString() { return StringFactory.makeFunctionString(this, this.constant); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/MapMap.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/MapMap.java index cfc03a2..2176295 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/MapMap.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/MapMap.java @@ -26,14 +26,12 @@ import org.apache.tinkerpop.machine.function.MapFunction; import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.util.StringFactory; -import java.util.Set; - /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class MapMap<C, S, E> extends AbstractFunction<C> implements MapFunction<C, S, E> { - private final Argument<E> argument; + private Argument<E> argument; private MapMap(final Coefficient<C> coefficient, final String label, final Argument<E> argument) { super(coefficient, label); @@ -50,6 +48,25 @@ public final class MapMap<C, S, E> extends AbstractFunction<C> implements MapFun return StringFactory.makeFunctionString(this, this.argument); } + @Override + public int hashCode() { + return this.argument.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof MapMap && + this.argument.equals(((MapMap) object).argument) && + super.equals(object); + } + + @Override + public MapMap<C, S, E> clone() { + final MapMap<C, S, E> clone = (MapMap<C, S, E>) super.clone(); + clone.argument = this.argument.clone(); + return clone; + } + public static <C, S, E> MapMap<C, S, E> compile(final Instruction<C> instruction) { return new MapMap<>(instruction.coefficient(), instruction.label(), Argument.create(instruction.args())); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/PathMap.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/PathMap.java index 75333a8..65eec4d 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/PathMap.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/PathMap.java @@ -30,7 +30,6 @@ import org.apache.tinkerpop.machine.traverser.path.Path; import java.util.ArrayList; import java.util.List; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -38,7 +37,7 @@ import java.util.Set; public final class PathMap<C, S> extends AbstractFunction<C> implements MapFunction<C, S, Path> { private final List<String> pathLabels; - private final CompilationCircle<C, Object, Object> byCompilations; + private CompilationCircle<C, Object, Object> byCompilations; private final boolean hasPathLabels; private final boolean hasByCompilations; @@ -71,6 +70,26 @@ public final class PathMap<C, S> extends AbstractFunction<C> implements MapFunct } } + @Override + public int hashCode() { + return super.hashCode() ^ this.pathLabels.hashCode() ^ this.byCompilations.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof PathMap && + this.pathLabels.equals(((PathMap) object).pathLabels) && + this.byCompilations.equals(((PathMap) object).byCompilations) && + super.equals(object); + } + + @Override + public PathMap<C, S> clone() { + final PathMap<C, S> clone = (PathMap<C, S>) super.clone(); + clone.byCompilations = this.byCompilations.clone(); + return clone; + } + public static <C, S> PathMap<C, S> compile(final Instruction<C> instruction) { final List<String> labels = new ArrayList<>(); final List<Compilation<C, Object, Object>> compilations = new ArrayList<>(); diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ValueMap.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ValueMap.java index d9b88c2..4461902 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ValueMap.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/map/ValueMap.java @@ -27,14 +27,12 @@ import org.apache.tinkerpop.machine.structure.data.TMap; import org.apache.tinkerpop.machine.traverser.Traverser; import org.apache.tinkerpop.machine.util.StringFactory; -import java.util.Set; - /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class ValueMap<C, K, V> extends AbstractFunction<C> implements MapFunction<C, TMap<K, V>, V> { - private final Argument<K> key; + private Argument<K> key; private ValueMap(final Coefficient<C> coefficient, final String label, final Argument<K> key) { super(coefficient, label); @@ -47,6 +45,25 @@ public final class ValueMap<C, K, V> extends AbstractFunction<C> implements MapF } @Override + public ValueMap<C, K, V> clone() { + final ValueMap<C, K, V> clone = (ValueMap<C, K, V>) super.clone(); + clone.key = this.key.clone(); + return clone; + } + + @Override + public int hashCode() { + return super.hashCode() ^ this.key.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof ValueMap && + this.key.equals(((ValueMap) object).key) && + super.equals(object); + } + + @Override public String toString() { return StringFactory.makeFunctionString(this, this.key); } diff --git a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java index 18b7df4..a90d0fc 100644 --- a/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java +++ b/java/machine/machine-core/src/main/java/org/apache/tinkerpop/machine/function/reduce/GroupCountReduce.java @@ -30,14 +30,13 @@ import org.apache.tinkerpop.machine.util.StringFactory; import java.util.HashMap; import java.util.Map; -import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ public final class GroupCountReduce<C, S, E> extends AbstractFunction<C> implements ReduceFunction<C, S, TMap<E, Long>> { - private final Compilation<C, S, E> byCompilation; + private Compilation<C, S, E> byCompilation; private GroupCountReduce(final Coefficient<C> coefficient, final String label, final Compilation<C, S, E> byCompilation) { super(coefficient, label); @@ -69,6 +68,25 @@ public final class GroupCountReduce<C, S, E> extends AbstractFunction<C> impleme return StringFactory.makeFunctionString(this, this.byCompilation); } + @Override + public int hashCode() { + return super.hashCode() ^ this.byCompilation.hashCode(); + } + + @Override + public boolean equals(final Object object) { + return object instanceof GroupCountReduce && + this.byCompilation.equals(((GroupCountReduce) object).byCompilation) && + super.equals(object); + } + + @Override + public GroupCountReduce<C, S, E> clone() { + final GroupCountReduce<C, S, E> clone = (GroupCountReduce<C, S, E>) super.clone(); + clone.byCompilation = this.byCompilation.clone(); + return clone; + } + public static <C, S, E> GroupCountReduce<C, S, E> compile(final Instruction<C> instruction) { return new GroupCountReduce<>(instruction.coefficient(), instruction.label(), Compilation.compileOrNull(0, instruction.args())); } diff --git a/java/machine/machine-core/src/test/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationTest.java b/java/machine/machine-core/src/test/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationTest.java new file mode 100644 index 0000000..bf89aed --- /dev/null +++ b/java/machine/machine-core/src/test/java/org/apache/tinkerpop/machine/bytecode/compiler/CompilationTest.java @@ -0,0 +1,62 @@ +/* + * 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.machine.bytecode.compiler; + +import org.apache.tinkerpop.machine.bytecode.Bytecode; +import org.apache.tinkerpop.machine.coefficient.LongCoefficient; +import org.apache.tinkerpop.machine.function.CFunction; +import org.apache.tinkerpop.machine.structure.data.TMap; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; + +/** + * @author Marko A. Rodriguez (http://markorodriguez.com) + */ +class CompilationTest { + + @Test + void shouldCloneCorrectly() { + final Bytecode<Long> bytecode = new Bytecode<>(); + final Bytecode<Long> inner = new Bytecode<>(); + inner.addInstruction(LongCoefficient.create(), CommonCompiler.Symbols.VALUE, "name"); + bytecode.addInstruction(LongCoefficient.create(), CommonCompiler.Symbols.HAS_KEY, "eq", inner); + bytecode.addInstruction(LongCoefficient.create(), CommonCompiler.Symbols.COUNT); + + final Compilation<Long, TMap, Long> compilationA = Compilation.compile(bytecode); + final Compilation<Long, TMap, Long> compilationB = compilationA.clone(); + assertEquals(compilationA.hashCode(), compilationB.hashCode()); + assertEquals(compilationA, compilationB); + assertNotSame(compilationA, compilationB); + + final List<CFunction<Long>> listA = compilationA.getFunctions(); + final List<CFunction<Long>> listB = compilationB.getFunctions(); + assertEquals(listA.hashCode(), listB.hashCode()); + assertEquals(listA, listB); + assertNotSame(listA, listB); + for (int i = 0; i < listA.size(); i++) { + assertEquals(listA.get(i).hashCode(), listB.get(i).hashCode()); + assertEquals(listA.get(i), listB.get(i)); + assertNotSame(listA.get(i), listB.get(i)); + } + } +}