From 5ecd123bfde635c7cf40a9ea39bff1d53b0ce3ca Mon Sep 17 00:00:00 2001 From: Mathieu Cloutier <79954947+cloutierMat@users.noreply.github.com> Date: Thu, 4 Jul 2024 14:28:02 -0600 Subject: [PATCH] Neptune support missing versions (#30) --- neptune-tinkerpop/3.4.11/pom.xml | 33 +++ .../traversal/step/util/HasContainer.java | 234 +++++++++++++++++ .../traversal/step/filter/HasLabelTest.java | 41 +++ .../tinkergraph/TinkerGraphProvider.java | 206 +++++++++++++++ neptune-tinkerpop/3.5.2/pom.xml | 33 +++ .../traversal/step/util/HasContainer.java | 240 ++++++++++++++++++ .../traversal/step/filter/HasLabelTest.java | 41 +++ .../tinkergraph/TinkerGraphProvider.java | 206 +++++++++++++++ neptune-tinkerpop/3.6.5/pom.xml | 33 +++ .../traversal/step/util/HasContainer.java | 236 +++++++++++++++++ .../traversal/step/filter/HasLabelTest.java | 41 +++ .../tinkergraph/TinkerGraphProvider.java | 206 +++++++++++++++ neptune-tinkerpop/3.7.1/pom.xml | 33 +++ .../traversal/step/util/HasContainer.java | 232 +++++++++++++++++ .../traversal/step/filter/HasLabelTest.java | 41 +++ .../tinkergraph/TinkerGraphProvider.java | 206 +++++++++++++++ neptune-tinkerpop/build.sh | 2 +- .../gremlin-core-3.4.11-patches.zip | Bin 0 -> 7826 bytes .../gremlin-core-3.5.2-patches.zip | Bin 0 -> 7855 bytes .../gremlin-core-3.6.2-patches.zip | Bin 7293 -> 7293 bytes .../gremlin-core-3.6.5-patches.zip | Bin 0 -> 7372 bytes .../gremlin-core-3.7.1-patches.zip | Bin 0 -> 7347 bytes 22 files changed, 2063 insertions(+), 1 deletion(-) create mode 100644 neptune-tinkerpop/3.4.11/pom.xml create mode 100644 neptune-tinkerpop/3.4.11/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java create mode 100644 neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java create mode 100644 neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java create mode 100644 neptune-tinkerpop/3.5.2/pom.xml create mode 100644 neptune-tinkerpop/3.5.2/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java create mode 100644 neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java create mode 100644 neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java create mode 100644 neptune-tinkerpop/3.6.5/pom.xml create mode 100644 neptune-tinkerpop/3.6.5/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java create mode 100644 neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java create mode 100644 neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java create mode 100644 neptune-tinkerpop/3.7.1/pom.xml create mode 100644 neptune-tinkerpop/3.7.1/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java create mode 100644 neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java create mode 100644 neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java create mode 100644 neptune-tinkerpop/gremlin-core-3.4.11-patches.zip create mode 100644 neptune-tinkerpop/gremlin-core-3.5.2-patches.zip create mode 100644 neptune-tinkerpop/gremlin-core-3.6.5-patches.zip create mode 100644 neptune-tinkerpop/gremlin-core-3.7.1-patches.zip diff --git a/neptune-tinkerpop/3.4.11/pom.xml b/neptune-tinkerpop/3.4.11/pom.xml new file mode 100644 index 0000000..3a9ba56 --- /dev/null +++ b/neptune-tinkerpop/3.4.11/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cloud.localstack + neptune-tinkerpop-gremlin + 0.1 + jar + + + 1.8 + 1.8 + + + + + org.apache.tinkerpop + gremlin-core + 3.4.11 + + + org.apache.tinkerpop + tinkergraph-gremlin + 3.4.11 + + + org.apache.tinkerpop + gremlin-test + 3.4.11 + + + diff --git a/neptune-tinkerpop/3.4.11/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/neptune-tinkerpop/3.4.11/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java new file mode 100644 index 0000000..3bee398 --- /dev/null +++ b/neptune-tinkerpop/3.4.11/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java @@ -0,0 +1,234 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package org.apache.tinkerpop.gremlin.process.traversal.step.util; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import org.apache.tinkerpop.gremlin.process.traversal.Compare; +import org.apache.tinkerpop.gremlin.process.traversal.Contains; +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.structure.Element; +import org.apache.tinkerpop.gremlin.structure.Property; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; + +public class HasContainer implements Serializable, Cloneable, Predicate { + + public static final String LABEL_DELIMITER = "::"; + + private String key; + private P predicate; + private final boolean testingIdString; + + public HasContainer(final String key, final P predicate) { + this.key = key; + this.predicate = predicate; + if (!this.key.equals(T.id.getAccessor())) { + this.testingIdString = false; + } else { + Object predicateValue = this.predicate.getValue(); + this.enforceHomogenousCollectionIfPresent(predicateValue); + Object valueInstance = this.predicate.getValue() instanceof Collection ? (((Collection)this.predicate.getValue()).isEmpty() ? new Object() : ((Collection)this.predicate.getValue()).toArray()[0]) : this.predicate.getValue(); + this.testingIdString = this.key.equals(T.id.getAccessor()) && valueInstance instanceof String; + if (this.testingIdString) { + this.predicate.setValue(this.predicate.getValue() instanceof Collection ? IteratorUtils.set(IteratorUtils.map(((Collection)this.predicate.getValue()).iterator(), Object::toString)) : this.predicate.getValue().toString()); + } + } + + } + + public final boolean test(final Element element) { + if (this.key.equals(T.id.getAccessor())) { + return this.testingIdString ? this.testIdAsString(element) : this.testId(element); + } else if (this.key.equals(T.label.getAccessor())) { + return this.testLabel(element); + } else { + Iterator itty = element.properties(new String[]{this.key}); + + try { + while(itty.hasNext()) { + if (this.testValue((Property)itty.next())) { + boolean var3 = true; + return var3; + } + } + } finally { + CloseableIterator.closeIterator(itty); + } + + return false; + } + } + + public final boolean test(final Property property) { + if (this.key.equals(T.value.getAccessor())) { + return this.testValue(property); + } else if (this.key.equals(T.key.getAccessor())) { + return this.testKey(property); + } else { + return property instanceof Element ? this.test((Element)property) : false; + } + } + + protected boolean testId(Element element) { + return this.predicate.test(element.id()); + } + + protected boolean testIdAsString(Element element) { + return this.predicate.test(element.id().toString()); + } + + protected boolean testLabel(Element element) { + + /* start patch for localstack */ + + // add comparison predicates to support the multi-label syntax `label1::label2::label3` + + class LabelEquals implements BiPredicate { + public boolean test(String label, String otherLabel) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (partialLabel.equals(otherLabel)) { + return true; + } + } + return false; + } + } + + class LabelWithin implements BiPredicate> { + public boolean test(String label, List labels) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (labels.contains(partialLabel)) { + return true; + } + } + return false; + } + } + + if (this.predicate.getBiPredicate() == Compare.eq && this.predicate.getValue() instanceof String) { + this.predicate = new P(new LabelEquals(), this.predicate.getValue()); + } else if (this.predicate.getBiPredicate() == Contains.within){ + if (this.predicate.getValue() instanceof String[]) { + // this should catch all hasLabel('LabelX') requests + final List labelsList = Arrays.asList((String[])this.predicate.getValue()); + this.predicate = new P(new LabelWithin(), labelsList); + } else if (this.predicate.getValue() instanceof List){ + // this should handle the traverse logic for hasLabel('LabelX', 'LabelXYZ') e.g. any match from that list + boolean validatedAllStrings = true; + for (Object s : (List) this.predicate.getValue()){ + // not sure if we can rely on having only Strings here + // verify the content before casting + if(! (s instanceof String)){ + validatedAllStrings = false; + break; + } + } + if (validatedAllStrings) this.predicate = new P(new LabelWithin(), this.predicate.getValue()); + } + } + + /* end patch for localstack */ + return this.predicate.test(element.label()); + } + + protected boolean testValue(Property property) { + return this.predicate.test(property.value()); + } + + protected boolean testKey(Property property) { + return this.predicate.test(property.key()); + } + + public final String toString() { + return this.key + '.' + this.predicate; + } + + public HasContainer clone() { + try { + HasContainer clone = (HasContainer)super.clone(); + clone.predicate = this.predicate.clone(); + return clone; + } catch (CloneNotSupportedException var2) { + CloneNotSupportedException e = var2; + throw new IllegalStateException(e.getMessage(), e); + } + } + + public int hashCode() { + return (this.key != null ? this.key.hashCode() : 0) ^ (this.predicate != null ? this.predicate.hashCode() : 0); + } + + public final String getKey() { + return this.key; + } + + public final void setKey(final String key) { + this.key = key; + } + + public final P getPredicate() { + return this.predicate; + } + + public final BiPredicate getBiPredicate() { + return this.predicate.getBiPredicate(); + } + + public final Object getValue() { + return this.predicate.getValue(); + } + + private void enforceHomogenousCollectionIfPresent(final Object predicateValue) { + if (predicateValue instanceof Collection) { + Collection collection = (Collection)predicateValue; + if (!collection.isEmpty()) { + Class first = collection.toArray()[0].getClass(); + if (!((Collection)predicateValue).stream().map(Object::getClass).allMatch((c) -> { + return first.equals(c); + })) { + throw new IllegalArgumentException("Has comparisons on a collection of ids require ids to all be of the same type"); + } + } + } + + } + + public static boolean testAll(final Property property, final List hasContainers) { + return internalTestAll(property, hasContainers); + } + + public static boolean testAll(final Element element, final List hasContainers) { + return internalTestAll(element, hasContainers); + } + + private static boolean internalTestAll(final S element, final List hasContainers) { + boolean isProperty = element instanceof Property; + Iterator var3 = hasContainers.iterator(); + + while(var3.hasNext()) { + HasContainer hasContainer = (HasContainer)var3.next(); + if (isProperty) { + if (!hasContainer.test((Property)element)) { + return false; + } + } else if (!hasContainer.test((Element)element)) { + return false; + } + } + + return true; + } +} diff --git a/neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java b/neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java new file mode 100644 index 0000000..4e5b385 --- /dev/null +++ b/neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java @@ -0,0 +1,41 @@ +package org.apache.tinkerpop.gremlin.process.traversal.step.filter; + +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; + +import org.apache.tinkerpop.gremlin.AbstractGremlinTest; +import org.apache.tinkerpop.gremlin.GraphManager; +import org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphProvider; + +public class HasLabelTest extends AbstractGremlinTest +{ + public HasLabelTest() { + GraphManager.setGraphProvider(new TinkerGraphProvider()); + } + + @Test + @LoadGraphWith(MODERN) + public void testHasLabelMultiValue() { + final String label1 = "l" + Math.random(); + final String label2 = "l" + Math.random(); + final String label3 = "l" + Math.random(); + + // add a couple of vertices with single labels and multi-labels + g.addV(label1).iterate(); + g.addV(label2).iterate(); + g.addV(label3).iterate(); + g.addV(label1 + "::" + label2).iterate(); + g.addV(label1 + "::" + label2 + "::" + label1).iterate(); + + // assert that vertices can be selected via single sub-labels + assertEquals(g.V().hasLabel(label1).toList().size(), 3); + assertEquals(g.V().hasLabel(label1).hasLabel(label2).toList().size(), 2); + + // assert that vertices can be selected via a set of alternative sub-labels + assertEquals(g.V().hasLabel(label1, label2).toList().size(), 4); + assertEquals(g.V().hasLabel(label1, label2, label3).toList().size(), 5); + } +} diff --git a/neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java b/neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java new file mode 100644 index 0000000..0efd240 --- /dev/null +++ b/neptune-tinkerpop/3.4.11/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java @@ -0,0 +1,206 @@ +/* + * 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.tinkergraph; + +import org.apache.commons.configuration.Configuration; +import org.apache.tinkerpop.gremlin.AbstractGraphProvider; +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.apache.tinkerpop.gremlin.TestHelper; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.GraphTest; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.structure.io.IoEdgeTest; +import org.apache.tinkerpop.gremlin.structure.io.IoVertexTest; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedGraphTest; +import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphTest; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerEdge; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerElement; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphVariables; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerProperty; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class TinkerGraphProvider extends AbstractGraphProvider { + + private static final Set IMPLEMENTATION = new HashSet() {{ + add(TinkerEdge.class); + add(TinkerElement.class); + add(TinkerGraph.class); + add(TinkerGraphVariables.class); + add(TinkerProperty.class); + add(TinkerVertex.class); + add(TinkerVertexProperty.class); + }}; + + @Override + public Map getBaseConfiguration(final String graphName, final Class test, final String testMethodName, + final LoadGraphWith.GraphData loadGraphWith) { + final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith); + final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromTest(test, testMethodName) : idManager).name(); + return new HashMap() {{ + put(Graph.GRAPH, TinkerGraph.class.getName()); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_EDGE_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, idMaker); + if (requiresListCardinalityAsDefault(loadGraphWith, test, testMethodName)) + put(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name()); + if (requiresPersistence(test, testMethodName)) { + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo"); + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION,TestHelper.makeTestDataFile(test, "temp", testMethodName + ".kryo")); + } + }}; + } + + @Override + public void clear(final Graph graph, final Configuration configuration) throws Exception { + if (graph != null) + graph.close(); + + // in the even the graph is persisted we need to clean up + final String graphLocation = null != configuration ? configuration.getString(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, null) : null; + if (graphLocation != null) { + final File f = new File(graphLocation); + f.delete(); + } + } + + @Override + public Set getImplementations() { + return IMPLEMENTATION; + } + + /** + * Determines if a test requires TinkerGraph persistence to be configured with graph location and format. + */ + protected static boolean requiresPersistence(final Class test, final String testMethodName) { + return test == GraphTest.class && testMethodName.equals("shouldPersistDataOnClose"); + } + + /** + * Determines if a test requires a different cardinality as the default or not. + */ + protected static boolean requiresListCardinalityAsDefault(final LoadGraphWith.GraphData loadGraphWith, + final Class test, final String testMethodName) { + return loadGraphWith == LoadGraphWith.GraphData.CREW + || (test == StarGraphTest.class && testMethodName.equals("shouldAttachWithCreateMethod")) + || (test == DetachedGraphTest.class && testMethodName.equals("testAttachableCreateMethod")); + } + + /** + * Some tests require special configuration for TinkerGraph to properly configure the id manager. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromTest(final Class test, final String testMethodName) { + if (test.equals(GraphTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentations"); + }}; + + final Set testsThatNeedUuidIdManager = new HashSet(){{ + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentations"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + else if (testsThatNeedUuidIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.UUID; + } else if (test.equals(IoEdgeTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteEdge[graphson-v1]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v1]"); + add("shouldReadWriteDetachedEdge[graphson-v1]"); + add("shouldReadWriteEdge[graphson-v2]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v2]"); + add("shouldReadWriteDetachedEdge[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } else if (test.equals(IoVertexTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteVertexWithBOTHEdges[graphson-v1]"); + add("shouldReadWriteVertexWithINEdges[graphson-v1]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v1]"); + add("shouldReadWriteVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v1]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v1]"); + add("shouldReadWriteVertexWithBOTHEdges[graphson-v2]"); + add("shouldReadWriteVertexWithINEdges[graphson-v2]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v2]"); + add("shouldReadWriteVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v2]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } + + return TinkerGraph.DefaultIdManager.ANY; + } + + /** + * Test that load with specific graph data can be configured with a specific id manager as the data type to + * be used in the test for that graph is known. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromGraphData(final LoadGraphWith.GraphData loadGraphWith) { + if (null == loadGraphWith) return TinkerGraph.DefaultIdManager.ANY; + if (loadGraphWith.equals(LoadGraphWith.GraphData.CLASSIC)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.MODERN)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.CREW)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.GRATEFUL)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.SINK)) + return TinkerGraph.DefaultIdManager.INTEGER; + else + throw new IllegalStateException(String.format("Need to define a new %s for %s", TinkerGraph.IdManager.class.getName(), loadGraphWith.name())); + } +} diff --git a/neptune-tinkerpop/3.5.2/pom.xml b/neptune-tinkerpop/3.5.2/pom.xml new file mode 100644 index 0000000..6500be2 --- /dev/null +++ b/neptune-tinkerpop/3.5.2/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cloud.localstack + neptune-tinkerpop-gremlin + 0.1 + jar + + + 1.8 + 1.8 + + + + + org.apache.tinkerpop + gremlin-core + 3.5.2 + + + org.apache.tinkerpop + tinkergraph-gremlin + 3.5.2 + + + org.apache.tinkerpop + gremlin-test + 3.5.2 + + + diff --git a/neptune-tinkerpop/3.5.2/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/neptune-tinkerpop/3.5.2/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java new file mode 100644 index 0000000..53a0b18 --- /dev/null +++ b/neptune-tinkerpop/3.5.2/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java @@ -0,0 +1,240 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package org.apache.tinkerpop.gremlin.process.traversal.step.util; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import org.apache.tinkerpop.gremlin.process.traversal.Compare; +import org.apache.tinkerpop.gremlin.process.traversal.Contains; +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.structure.Element; +import org.apache.tinkerpop.gremlin.structure.Property; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; + +public class HasContainer implements Serializable, Cloneable, Predicate { + + public static final String LABEL_DELIMITER = "::"; + + private String key; + private P predicate; + private final boolean testingIdString; + + public HasContainer(final String key, final P predicate) { + this.key = key; + this.predicate = predicate; + if (!this.key.equals(T.id.getAccessor())) { + this.testingIdString = false; + } else { + Object predicateValue = this.predicate.getValue(); + this.enforceHomogenousCollectionIfPresent(predicateValue); + Object valueInstance = this.predicate.getValue() instanceof Collection ? (((Collection)this.predicate.getValue()).isEmpty() ? new Object() : ((Collection)this.predicate.getValue()).toArray()[0]) : this.predicate.getValue(); + this.testingIdString = this.key.equals(T.id.getAccessor()) && valueInstance instanceof String; + if (this.testingIdString) { + this.predicate.setValue(this.predicate.getValue() instanceof Collection ? IteratorUtils.set(IteratorUtils.map(((Collection)this.predicate.getValue()).iterator(), Object::toString)) : this.predicate.getValue().toString()); + } + } + + } + + public final boolean test(final Element element) { + if (this.key.equals(T.id.getAccessor())) { + return this.testingIdString ? this.testIdAsString(element) : this.testId(element); + } else if (this.key.equals(T.label.getAccessor())) { + return this.testLabel(element); + } else { + Iterator itty = element.properties(new String[]{this.key}); + + while(true) { + boolean var3; + try { + if (!itty.hasNext()) { + return false; + } + + if (!this.testValue((Property)itty.next())) { + continue; + } + + var3 = true; + } finally { + CloseableIterator.closeIterator(itty); + } + + return var3; + } + } + } + + public final boolean test(final Property property) { + if (this.key.equals(T.value.getAccessor())) { + return this.testValue(property); + } else if (this.key.equals(T.key.getAccessor())) { + return this.testKey(property); + } else { + return property instanceof Element ? this.test((Element)property) : false; + } + } + + protected boolean testId(final Element element) { + return this.predicate.test(element.id()); + } + + protected boolean testIdAsString(final Element element) { + return this.predicate.test(element.id().toString()); + } + + protected boolean testLabel(final Element element) { + + /* start patch for localstack */ + + // add comparison predicates to support the multi-label syntax `label1::label2::label3` + + class LabelEquals implements BiPredicate { + public boolean test(String label, String otherLabel) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (partialLabel.equals(otherLabel)) { + return true; + } + } + return false; + } + } + + class LabelWithin implements BiPredicate> { + public boolean test(String label, List labels) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (labels.contains(partialLabel)) { + return true; + } + } + return false; + } + } + + if (this.predicate.getBiPredicate() == Compare.eq && this.predicate.getValue() instanceof String) { + this.predicate = new P(new LabelEquals(), this.predicate.getValue()); + } else if (this.predicate.getBiPredicate() == Contains.within){ + if (this.predicate.getValue() instanceof String[]) { + // this should catch all hasLabel('LabelX') requests + final List labelsList = Arrays.asList((String[])this.predicate.getValue()); + this.predicate = new P(new LabelWithin(), labelsList); + } else if (this.predicate.getValue() instanceof List){ + // this should handle the traverse logic for hasLabel('LabelX', 'LabelXYZ') e.g. any match from that list + boolean validatedAllStrings = true; + for (Object s : (List) this.predicate.getValue()){ + // not sure if we can rely on having only Strings here + // verify the content before casting + if(! (s instanceof String)){ + validatedAllStrings = false; + break; + } + } + if (validatedAllStrings) this.predicate = new P(new LabelWithin(), this.predicate.getValue()); + } + } + + /* end patch for localstack */ + return this.predicate.test(element.label()); + } + + protected boolean testValue(final Property property) { + return this.predicate.test(property.value()); + } + + protected boolean testKey(final Property property) { + return this.predicate.test(property.key()); + } + + public final String toString() { + return this.key + '.' + this.predicate; + } + + public HasContainer clone() { + try { + HasContainer clone = (HasContainer)super.clone(); + clone.predicate = this.predicate.clone(); + return clone; + } catch (CloneNotSupportedException var2) { + CloneNotSupportedException e = var2; + throw new IllegalStateException(e.getMessage(), e); + } + } + + public int hashCode() { + return (this.key != null ? this.key.hashCode() : 0) ^ (this.predicate != null ? this.predicate.hashCode() : 0); + } + + public final String getKey() { + return this.key; + } + + public final void setKey(final String key) { + this.key = key; + } + + public final P getPredicate() { + return this.predicate; + } + + public final BiPredicate getBiPredicate() { + return this.predicate.getBiPredicate(); + } + + public final Object getValue() { + return this.predicate.getValue(); + } + + private void enforceHomogenousCollectionIfPresent(final Object predicateValue) { + if (predicateValue instanceof Collection) { + Collection collection = (Collection)predicateValue; + if (!collection.isEmpty()) { + Class first = collection.toArray()[0].getClass(); + if (!((Collection)predicateValue).stream().map(Object::getClass).allMatch((c) -> { + return first.equals(c); + })) { + throw new IllegalArgumentException("Has comparisons on a collection of ids require ids to all be of the same type"); + } + } + } + + } + + public static boolean testAll(final Property property, final List hasContainers) { + return internalTestAll(property, hasContainers); + } + + public static boolean testAll(final Element element, final List hasContainers) { + return internalTestAll(element, hasContainers); + } + + private static boolean internalTestAll(final S element, final List hasContainers) { + boolean isProperty = element instanceof Property; + Iterator var3 = hasContainers.iterator(); + + while(var3.hasNext()) { + HasContainer hasContainer = (HasContainer)var3.next(); + if (isProperty) { + if (!hasContainer.test((Property)element)) { + return false; + } + } else if (!hasContainer.test((Element)element)) { + return false; + } + } + + return true; + } +} diff --git a/neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java b/neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java new file mode 100644 index 0000000..4e5b385 --- /dev/null +++ b/neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java @@ -0,0 +1,41 @@ +package org.apache.tinkerpop.gremlin.process.traversal.step.filter; + +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; + +import org.apache.tinkerpop.gremlin.AbstractGremlinTest; +import org.apache.tinkerpop.gremlin.GraphManager; +import org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphProvider; + +public class HasLabelTest extends AbstractGremlinTest +{ + public HasLabelTest() { + GraphManager.setGraphProvider(new TinkerGraphProvider()); + } + + @Test + @LoadGraphWith(MODERN) + public void testHasLabelMultiValue() { + final String label1 = "l" + Math.random(); + final String label2 = "l" + Math.random(); + final String label3 = "l" + Math.random(); + + // add a couple of vertices with single labels and multi-labels + g.addV(label1).iterate(); + g.addV(label2).iterate(); + g.addV(label3).iterate(); + g.addV(label1 + "::" + label2).iterate(); + g.addV(label1 + "::" + label2 + "::" + label1).iterate(); + + // assert that vertices can be selected via single sub-labels + assertEquals(g.V().hasLabel(label1).toList().size(), 3); + assertEquals(g.V().hasLabel(label1).hasLabel(label2).toList().size(), 2); + + // assert that vertices can be selected via a set of alternative sub-labels + assertEquals(g.V().hasLabel(label1, label2).toList().size(), 4); + assertEquals(g.V().hasLabel(label1, label2, label3).toList().size(), 5); + } +} diff --git a/neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java b/neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java new file mode 100644 index 0000000..3254aa1 --- /dev/null +++ b/neptune-tinkerpop/3.5.2/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java @@ -0,0 +1,206 @@ +/* + * 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.tinkergraph; + +import org.apache.commons.configuration2.Configuration; +import org.apache.tinkerpop.gremlin.AbstractGraphProvider; +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.apache.tinkerpop.gremlin.TestHelper; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.GraphTest; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.structure.io.IoEdgeTest; +import org.apache.tinkerpop.gremlin.structure.io.IoVertexTest; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedGraphTest; +import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphTest; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerEdge; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerElement; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphVariables; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerProperty; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class TinkerGraphProvider extends AbstractGraphProvider { + + private static final Set IMPLEMENTATION = new HashSet() {{ + add(TinkerEdge.class); + add(TinkerElement.class); + add(TinkerGraph.class); + add(TinkerGraphVariables.class); + add(TinkerProperty.class); + add(TinkerVertex.class); + add(TinkerVertexProperty.class); + }}; + + @Override + public Map getBaseConfiguration(final String graphName, final Class test, final String testMethodName, + final LoadGraphWith.GraphData loadGraphWith) { + final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith); + final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromTest(test, testMethodName) : idManager).name(); + return new HashMap() {{ + put(Graph.GRAPH, TinkerGraph.class.getName()); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_EDGE_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, idMaker); + if (requiresListCardinalityAsDefault(loadGraphWith, test, testMethodName)) + put(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name()); + if (requiresPersistence(test, testMethodName)) { + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo"); + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION,TestHelper.makeTestDataFile(test, "temp", testMethodName + ".kryo")); + } + }}; + } + + @Override + public void clear(final Graph graph, final Configuration configuration) throws Exception { + if (graph != null) + graph.close(); + + // in the even the graph is persisted we need to clean up + final String graphLocation = null != configuration ? configuration.getString(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, null) : null; + if (graphLocation != null) { + final File f = new File(graphLocation); + f.delete(); + } + } + + @Override + public Set getImplementations() { + return IMPLEMENTATION; + } + + /** + * Determines if a test requires TinkerGraph persistence to be configured with graph location and format. + */ + protected static boolean requiresPersistence(final Class test, final String testMethodName) { + return test == GraphTest.class && testMethodName.equals("shouldPersistDataOnClose"); + } + + /** + * Determines if a test requires a different cardinality as the default or not. + */ + protected static boolean requiresListCardinalityAsDefault(final LoadGraphWith.GraphData loadGraphWith, + final Class test, final String testMethodName) { + return loadGraphWith == LoadGraphWith.GraphData.CREW + || (test == StarGraphTest.class && testMethodName.equals("shouldAttachWithCreateMethod")) + || (test == DetachedGraphTest.class && testMethodName.equals("testAttachableCreateMethod")); + } + + /** + * Some tests require special configuration for TinkerGraph to properly configure the id manager. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromTest(final Class test, final String testMethodName) { + if (test.equals(GraphTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentations"); + }}; + + final Set testsThatNeedUuidIdManager = new HashSet(){{ + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentations"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + else if (testsThatNeedUuidIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.UUID; + } else if (test.equals(IoEdgeTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteEdge[graphson-v1]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v1]"); + add("shouldReadWriteDetachedEdge[graphson-v1]"); + add("shouldReadWriteEdge[graphson-v2]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v2]"); + add("shouldReadWriteDetachedEdge[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } else if (test.equals(IoVertexTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteVertexWithBOTHEdges[graphson-v1]"); + add("shouldReadWriteVertexWithINEdges[graphson-v1]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v1]"); + add("shouldReadWriteVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v1]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v1]"); + add("shouldReadWriteVertexWithBOTHEdges[graphson-v2]"); + add("shouldReadWriteVertexWithINEdges[graphson-v2]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v2]"); + add("shouldReadWriteVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v2]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } + + return TinkerGraph.DefaultIdManager.ANY; + } + + /** + * Test that load with specific graph data can be configured with a specific id manager as the data type to + * be used in the test for that graph is known. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromGraphData(final LoadGraphWith.GraphData loadGraphWith) { + if (null == loadGraphWith) return TinkerGraph.DefaultIdManager.ANY; + if (loadGraphWith.equals(LoadGraphWith.GraphData.CLASSIC)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.MODERN)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.CREW)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.GRATEFUL)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.SINK)) + return TinkerGraph.DefaultIdManager.INTEGER; + else + throw new IllegalStateException(String.format("Need to define a new %s for %s", TinkerGraph.IdManager.class.getName(), loadGraphWith.name())); + } +} diff --git a/neptune-tinkerpop/3.6.5/pom.xml b/neptune-tinkerpop/3.6.5/pom.xml new file mode 100644 index 0000000..19ea25c --- /dev/null +++ b/neptune-tinkerpop/3.6.5/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cloud.localstack + neptune-tinkerpop-gremlin + 0.1 + jar + + + 1.8 + 1.8 + + + + + org.apache.tinkerpop + gremlin-core + 3.6.5 + + + org.apache.tinkerpop + tinkergraph-gremlin + 3.6.5 + + + org.apache.tinkerpop + gremlin-test + 3.6.5 + + + diff --git a/neptune-tinkerpop/3.6.5/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/neptune-tinkerpop/3.6.5/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java new file mode 100644 index 0000000..42f505c --- /dev/null +++ b/neptune-tinkerpop/3.6.5/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java @@ -0,0 +1,236 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package org.apache.tinkerpop.gremlin.process.traversal.step.util; + +import java.io.Serializable; +import java.util.*; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import org.apache.tinkerpop.gremlin.process.traversal.Compare; +import org.apache.tinkerpop.gremlin.process.traversal.Contains; +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.structure.Element; +import org.apache.tinkerpop.gremlin.structure.Property; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator; + +public class HasContainer implements Serializable, Cloneable, Predicate { + + public static final String LABEL_DELIMITER = "::"; + + private String key; + private P predicate; + private final boolean testingIdString; + + public HasContainer(final String key, final P predicate) { + this.key = key; + this.predicate = predicate; + this.testingIdString = this.isStringTestable(); + } + + public final boolean test(final Element element) { + if (this.key != null) { + if (this.key.equals(T.id.getAccessor())) { + return this.testingIdString ? this.testIdAsString(element) : this.testId(element); + } + + if (this.key.equals(T.label.getAccessor())) { + return this.testLabel(element); + } + } + + Iterator itty = element.properties(new String[]{this.key}); + + while(true) { + boolean var3; + try { + if (!itty.hasNext()) { + return false; + } + + if (!this.testValue((Property)itty.next())) { + continue; + } + + var3 = true; + } finally { + CloseableIterator.closeIterator(itty); + } + + return var3; + } + } + + public final boolean test(final Property property) { + if (this.key != null) { + if (this.key.equals(T.value.getAccessor())) { + return this.testValue(property); + } + + if (this.key.equals(T.key.getAccessor())) { + return this.testKey(property); + } + } + + return property instanceof Element ? this.test((Element)property) : false; + } + + protected boolean testId(final Element element) { + return this.predicate.test(element.id()); + } + + protected boolean testIdAsString(final Element element) { + return this.predicate.test(element.id().toString()); + } + + protected boolean testLabel(final Element element) { + + /* start patch for localstack */ + + // add comparison predicates to support the multi-label syntax `label1::label2::label3` + + class LabelEquals implements BiPredicate { + public boolean test(String label, String otherLabel) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (partialLabel.equals(otherLabel)) { + return true; + } + } + return false; + } + } + + class LabelWithin implements BiPredicate> { + public boolean test(String label, List labels) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (labels.contains(partialLabel)) { + return true; + } + } + return false; + } + } + + if (this.predicate.getBiPredicate() == Compare.eq && this.predicate.getValue() instanceof String) { + this.predicate = new P(new LabelEquals(), this.predicate.getValue()); + } else if (this.predicate.getBiPredicate() == Contains.within){ + if (this.predicate.getValue() instanceof String[]) { + // this should catch all hasLabel('LabelX') requests + final List labelsList = Arrays.asList((String[])this.predicate.getValue()); + this.predicate = new P(new LabelWithin(), labelsList); + } else if (this.predicate.getValue() instanceof List){ + // this should handle the traverse logic for hasLabel('LabelX', 'LabelXYZ') e.g. any match from that list + boolean validatedAllStrings = true; + for (Object s : (List) this.predicate.getValue()){ + // not sure if we can rely on having only Strings here + // verify the content before casting + if(! (s instanceof String)){ + validatedAllStrings = false; + break; + } + } + if (validatedAllStrings) this.predicate = new P(new LabelWithin(), this.predicate.getValue()); + } + } + + /* end patch for localstack */ + return this.predicate.test(element.label()); + } + + protected boolean testValue(final Property property) { + return this.predicate.test(property.value()); + } + + protected boolean testKey(final Property property) { + return this.predicate.test(property.key()); + } + + public final String toString() { + return Objects.toString(this.key) + '.' + this.predicate; + } + + public HasContainer clone() { + try { + HasContainer clone = (HasContainer)super.clone(); + clone.predicate = this.predicate.clone(); + return clone; + } catch (CloneNotSupportedException var2) { + CloneNotSupportedException e = var2; + throw new IllegalStateException(e.getMessage(), e); + } + } + + public int hashCode() { + return (this.key != null ? this.key.hashCode() : 0) ^ (this.predicate != null ? this.predicate.hashCode() : 0); + } + + public final String getKey() { + return this.key; + } + + public final void setKey(final String key) { + this.key = key; + } + + public final P getPredicate() { + return this.predicate; + } + + public final BiPredicate getBiPredicate() { + return this.predicate.getBiPredicate(); + } + + public final Object getValue() { + return this.predicate.getValue(); + } + + private boolean isStringTestable() { + if (this.key != null && this.key.equals(T.id.getAccessor())) { + Object predicateValue = null == this.predicate ? null : this.predicate.getValue(); + if (predicateValue instanceof Collection) { + Collection collection = (Collection)predicateValue; + if (!collection.isEmpty()) { + return ((Collection)predicateValue).stream().allMatch((c) -> { + return null == c || c instanceof String; + }); + } + } + + return predicateValue instanceof String; + } else { + return false; + } + } + + public static boolean testAll(final Property property, final List hasContainers) { + return internalTestAll(property, hasContainers); + } + + public static boolean testAll(final Element element, final List hasContainers) { + return internalTestAll(element, hasContainers); + } + + private static boolean internalTestAll(final S element, final List hasContainers) { + boolean isProperty = element instanceof Property; + Iterator var3 = hasContainers.iterator(); + + while(var3.hasNext()) { + HasContainer hasContainer = (HasContainer)var3.next(); + if (isProperty) { + if (!hasContainer.test((Property)element)) { + return false; + } + } else if (!hasContainer.test((Element)element)) { + return false; + } + } + + return true; + } +} diff --git a/neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java b/neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java new file mode 100644 index 0000000..4e5b385 --- /dev/null +++ b/neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java @@ -0,0 +1,41 @@ +package org.apache.tinkerpop.gremlin.process.traversal.step.filter; + +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; + +import org.apache.tinkerpop.gremlin.AbstractGremlinTest; +import org.apache.tinkerpop.gremlin.GraphManager; +import org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphProvider; + +public class HasLabelTest extends AbstractGremlinTest +{ + public HasLabelTest() { + GraphManager.setGraphProvider(new TinkerGraphProvider()); + } + + @Test + @LoadGraphWith(MODERN) + public void testHasLabelMultiValue() { + final String label1 = "l" + Math.random(); + final String label2 = "l" + Math.random(); + final String label3 = "l" + Math.random(); + + // add a couple of vertices with single labels and multi-labels + g.addV(label1).iterate(); + g.addV(label2).iterate(); + g.addV(label3).iterate(); + g.addV(label1 + "::" + label2).iterate(); + g.addV(label1 + "::" + label2 + "::" + label1).iterate(); + + // assert that vertices can be selected via single sub-labels + assertEquals(g.V().hasLabel(label1).toList().size(), 3); + assertEquals(g.V().hasLabel(label1).hasLabel(label2).toList().size(), 2); + + // assert that vertices can be selected via a set of alternative sub-labels + assertEquals(g.V().hasLabel(label1, label2).toList().size(), 4); + assertEquals(g.V().hasLabel(label1, label2, label3).toList().size(), 5); + } +} diff --git a/neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java b/neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java new file mode 100644 index 0000000..3254aa1 --- /dev/null +++ b/neptune-tinkerpop/3.6.5/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java @@ -0,0 +1,206 @@ +/* + * 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.tinkergraph; + +import org.apache.commons.configuration2.Configuration; +import org.apache.tinkerpop.gremlin.AbstractGraphProvider; +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.apache.tinkerpop.gremlin.TestHelper; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.GraphTest; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.structure.io.IoEdgeTest; +import org.apache.tinkerpop.gremlin.structure.io.IoVertexTest; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedGraphTest; +import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphTest; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerEdge; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerElement; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphVariables; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerProperty; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class TinkerGraphProvider extends AbstractGraphProvider { + + private static final Set IMPLEMENTATION = new HashSet() {{ + add(TinkerEdge.class); + add(TinkerElement.class); + add(TinkerGraph.class); + add(TinkerGraphVariables.class); + add(TinkerProperty.class); + add(TinkerVertex.class); + add(TinkerVertexProperty.class); + }}; + + @Override + public Map getBaseConfiguration(final String graphName, final Class test, final String testMethodName, + final LoadGraphWith.GraphData loadGraphWith) { + final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith); + final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromTest(test, testMethodName) : idManager).name(); + return new HashMap() {{ + put(Graph.GRAPH, TinkerGraph.class.getName()); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_EDGE_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, idMaker); + if (requiresListCardinalityAsDefault(loadGraphWith, test, testMethodName)) + put(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name()); + if (requiresPersistence(test, testMethodName)) { + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo"); + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION,TestHelper.makeTestDataFile(test, "temp", testMethodName + ".kryo")); + } + }}; + } + + @Override + public void clear(final Graph graph, final Configuration configuration) throws Exception { + if (graph != null) + graph.close(); + + // in the even the graph is persisted we need to clean up + final String graphLocation = null != configuration ? configuration.getString(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, null) : null; + if (graphLocation != null) { + final File f = new File(graphLocation); + f.delete(); + } + } + + @Override + public Set getImplementations() { + return IMPLEMENTATION; + } + + /** + * Determines if a test requires TinkerGraph persistence to be configured with graph location and format. + */ + protected static boolean requiresPersistence(final Class test, final String testMethodName) { + return test == GraphTest.class && testMethodName.equals("shouldPersistDataOnClose"); + } + + /** + * Determines if a test requires a different cardinality as the default or not. + */ + protected static boolean requiresListCardinalityAsDefault(final LoadGraphWith.GraphData loadGraphWith, + final Class test, final String testMethodName) { + return loadGraphWith == LoadGraphWith.GraphData.CREW + || (test == StarGraphTest.class && testMethodName.equals("shouldAttachWithCreateMethod")) + || (test == DetachedGraphTest.class && testMethodName.equals("testAttachableCreateMethod")); + } + + /** + * Some tests require special configuration for TinkerGraph to properly configure the id manager. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromTest(final Class test, final String testMethodName) { + if (test.equals(GraphTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentations"); + }}; + + final Set testsThatNeedUuidIdManager = new HashSet(){{ + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentations"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + else if (testsThatNeedUuidIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.UUID; + } else if (test.equals(IoEdgeTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteEdge[graphson-v1]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v1]"); + add("shouldReadWriteDetachedEdge[graphson-v1]"); + add("shouldReadWriteEdge[graphson-v2]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v2]"); + add("shouldReadWriteDetachedEdge[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } else if (test.equals(IoVertexTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteVertexWithBOTHEdges[graphson-v1]"); + add("shouldReadWriteVertexWithINEdges[graphson-v1]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v1]"); + add("shouldReadWriteVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v1]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v1]"); + add("shouldReadWriteVertexWithBOTHEdges[graphson-v2]"); + add("shouldReadWriteVertexWithINEdges[graphson-v2]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v2]"); + add("shouldReadWriteVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v2]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } + + return TinkerGraph.DefaultIdManager.ANY; + } + + /** + * Test that load with specific graph data can be configured with a specific id manager as the data type to + * be used in the test for that graph is known. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromGraphData(final LoadGraphWith.GraphData loadGraphWith) { + if (null == loadGraphWith) return TinkerGraph.DefaultIdManager.ANY; + if (loadGraphWith.equals(LoadGraphWith.GraphData.CLASSIC)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.MODERN)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.CREW)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.GRATEFUL)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.SINK)) + return TinkerGraph.DefaultIdManager.INTEGER; + else + throw new IllegalStateException(String.format("Need to define a new %s for %s", TinkerGraph.IdManager.class.getName(), loadGraphWith.name())); + } +} diff --git a/neptune-tinkerpop/3.7.1/pom.xml b/neptune-tinkerpop/3.7.1/pom.xml new file mode 100644 index 0000000..865e0ee --- /dev/null +++ b/neptune-tinkerpop/3.7.1/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cloud.localstack + neptune-tinkerpop-gremlin + 0.1 + jar + + + 1.8 + 1.8 + + + + + org.apache.tinkerpop + gremlin-core + 3.7.1 + + + org.apache.tinkerpop + tinkergraph-gremlin + 3.7.1 + + + org.apache.tinkerpop + gremlin-test + 3.7.1 + + + diff --git a/neptune-tinkerpop/3.7.1/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/neptune-tinkerpop/3.7.1/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java new file mode 100644 index 0000000..81d1dab --- /dev/null +++ b/neptune-tinkerpop/3.7.1/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java @@ -0,0 +1,232 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package org.apache.tinkerpop.gremlin.process.traversal.step.util; + +import java.io.Serializable; +import java.util.*; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import org.apache.tinkerpop.gremlin.process.traversal.Compare; +import org.apache.tinkerpop.gremlin.process.traversal.Contains; +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.PBiPredicate; +import org.apache.tinkerpop.gremlin.structure.Element; +import org.apache.tinkerpop.gremlin.structure.Property; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator; + + +public class HasContainer implements Serializable, Cloneable, Predicate { + + public static final String LABEL_DELIMITER = "::"; + + private String key; + private P predicate; + private final boolean testingIdString; + + public HasContainer(final String key, final P predicate) { + this.key = key; + this.predicate = predicate; + this.testingIdString = this.isStringTestable(); + } + + public final boolean test(final Element element) { + if (this.key != null) { + if (this.key.equals(T.id.getAccessor())) { + return this.testingIdString ? this.testIdAsString(element) : this.testId(element); + } + if (this.key.equals(T.label.getAccessor())) { + return this.testLabel(element); + } + } + + Iterator itty = element.properties(new String[]{this.key}); + + try { + while(itty.hasNext()) { + if (this.testValue((Property)itty.next())) { + boolean var3 = true; + return var3; + } + } + } finally { + CloseableIterator.closeIterator(itty); + } + + return false; + } + + public final boolean test(final Property property) { + if (this.key != null) { + if (this.key.equals(T.value.getAccessor())) { + return this.testValue(property); + } + + if (this.key.equals(T.key.getAccessor())) { + return this.testKey(property); + } + } + + return property instanceof Element ? this.test((Element)property) : false; + } + + protected boolean testId(final Element element) { + return this.predicate.test(element.id()); + } + + protected boolean testIdAsString(final Element element) { + return this.predicate.test(element.id().toString()); + } + + protected boolean testLabel(final Element element) { + + /* start patch for localstack */ + + // add comparison predicates to support the multi-label syntax `label1::label2::label3` + + class LabelEquals implements PBiPredicate { + public boolean test(String label, String otherLabel) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (partialLabel.equals(otherLabel)) { + return true; + } + } + return false; + } + } + + class LabelWithin implements PBiPredicate> { + public boolean test(String label, List labels) { + if (label == null) return false; + for (String partialLabel: label.split(LABEL_DELIMITER)) { + if (labels.contains(partialLabel)) { + return true; + } + } + return false; + } + } + + if (this.predicate.getBiPredicate() == Compare.eq && this.predicate.getValue() instanceof String) { + this.predicate = new P(new LabelEquals(), this.predicate.getValue()); + } else if (this.predicate.getBiPredicate() == Contains.within){ + if (this.predicate.getValue() instanceof String[]) { + // this should catch all hasLabel('LabelX') requests + final List labelsList = Arrays.asList((String[])this.predicate.getValue()); + this.predicate = new P(new LabelWithin(), labelsList); + } else if (this.predicate.getValue() instanceof List){ + // this should handle the traverse logic for hasLabel('LabelX', 'LabelXYZ') e.g. any match from that list + boolean validatedAllStrings = true; + for (Object s : (List) this.predicate.getValue()){ + // not sure if we can rely on having only Strings here + // verify the content before casting + if(! (s instanceof String)){ + validatedAllStrings = false; + break; + } + } + if (validatedAllStrings) this.predicate = new P(new LabelWithin(), this.predicate.getValue()); + } + } + + /* end patch for localstack */ + + return this.predicate.test(element.label()); + } + + protected boolean testValue(final Property property) { + return this.predicate.test(property.value()); + } + + protected boolean testKey(final Property property) { + return this.predicate.test(property.key()); + } + + public final String toString() { + return Objects.toString(this.key) + '.' + this.predicate; + } + + public HasContainer clone() { + try { + HasContainer clone = (HasContainer)super.clone(); + clone.predicate = this.predicate.clone(); + return clone; + } catch (CloneNotSupportedException var2) { + CloneNotSupportedException e = var2; + throw new IllegalStateException(e.getMessage(), e); + } + } + + public int hashCode() { + return (this.key != null ? this.key.hashCode() : 0) ^ (this.predicate != null ? this.predicate.hashCode() : 0); + } + + public final String getKey() { + return this.key; + } + + public final void setKey(final String key) { + this.key = key; + } + + public final P getPredicate() { + return this.predicate; + } + + public final BiPredicate getBiPredicate() { + return this.predicate.getBiPredicate(); + } + + public final Object getValue() { + return this.predicate.getValue(); + } + + private boolean isStringTestable() { + if (this.key != null && this.key.equals(T.id.getAccessor())) { + Object predicateValue = null == this.predicate ? null : this.predicate.getValue(); + if (predicateValue instanceof Collection) { + Collection collection = (Collection)predicateValue; + if (!collection.isEmpty()) { + return ((Collection)predicateValue).stream().allMatch((c) -> { + return null == c || c instanceof String; + }); + } + } + + return predicateValue instanceof String; + } else { + return false; + } + } + + public static boolean testAll(final Property property, final List hasContainers) { + return internalTestAll(property, hasContainers); + } + + public static boolean testAll(final Element element, final List hasContainers) { + return internalTestAll(element, hasContainers); + } + + private static boolean internalTestAll(final S element, final List hasContainers) { + boolean isProperty = element instanceof Property; + Iterator var3 = hasContainers.iterator(); + + while(var3.hasNext()) { + HasContainer hasContainer = (HasContainer)var3.next(); + if (isProperty) { + if (!hasContainer.test((Property)element)) { + return false; + } + } else if (!hasContainer.test((Element)element)) { + return false; + } + } + + return true; + } +} diff --git a/neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java b/neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java new file mode 100644 index 0000000..4e5b385 --- /dev/null +++ b/neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasLabelTest.java @@ -0,0 +1,41 @@ +package org.apache.tinkerpop.gremlin.process.traversal.step.filter; + +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; + +import org.apache.tinkerpop.gremlin.AbstractGremlinTest; +import org.apache.tinkerpop.gremlin.GraphManager; +import org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphProvider; + +public class HasLabelTest extends AbstractGremlinTest +{ + public HasLabelTest() { + GraphManager.setGraphProvider(new TinkerGraphProvider()); + } + + @Test + @LoadGraphWith(MODERN) + public void testHasLabelMultiValue() { + final String label1 = "l" + Math.random(); + final String label2 = "l" + Math.random(); + final String label3 = "l" + Math.random(); + + // add a couple of vertices with single labels and multi-labels + g.addV(label1).iterate(); + g.addV(label2).iterate(); + g.addV(label3).iterate(); + g.addV(label1 + "::" + label2).iterate(); + g.addV(label1 + "::" + label2 + "::" + label1).iterate(); + + // assert that vertices can be selected via single sub-labels + assertEquals(g.V().hasLabel(label1).toList().size(), 3); + assertEquals(g.V().hasLabel(label1).hasLabel(label2).toList().size(), 2); + + // assert that vertices can be selected via a set of alternative sub-labels + assertEquals(g.V().hasLabel(label1, label2).toList().size(), 4); + assertEquals(g.V().hasLabel(label1, label2, label3).toList().size(), 5); + } +} diff --git a/neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java b/neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java new file mode 100644 index 0000000..3254aa1 --- /dev/null +++ b/neptune-tinkerpop/3.7.1/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphProvider.java @@ -0,0 +1,206 @@ +/* + * 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.tinkergraph; + +import org.apache.commons.configuration2.Configuration; +import org.apache.tinkerpop.gremlin.AbstractGraphProvider; +import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.apache.tinkerpop.gremlin.TestHelper; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.GraphTest; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.structure.io.IoEdgeTest; +import org.apache.tinkerpop.gremlin.structure.io.IoVertexTest; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedGraphTest; +import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphTest; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerEdge; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerElement; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphVariables; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerProperty; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class TinkerGraphProvider extends AbstractGraphProvider { + + private static final Set IMPLEMENTATION = new HashSet() {{ + add(TinkerEdge.class); + add(TinkerElement.class); + add(TinkerGraph.class); + add(TinkerGraphVariables.class); + add(TinkerProperty.class); + add(TinkerVertex.class); + add(TinkerVertexProperty.class); + }}; + + @Override + public Map getBaseConfiguration(final String graphName, final Class test, final String testMethodName, + final LoadGraphWith.GraphData loadGraphWith) { + final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith); + final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromTest(test, testMethodName) : idManager).name(); + return new HashMap() {{ + put(Graph.GRAPH, TinkerGraph.class.getName()); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_EDGE_ID_MANAGER, idMaker); + put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, idMaker); + if (requiresListCardinalityAsDefault(loadGraphWith, test, testMethodName)) + put(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name()); + if (requiresPersistence(test, testMethodName)) { + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo"); + put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION,TestHelper.makeTestDataFile(test, "temp", testMethodName + ".kryo")); + } + }}; + } + + @Override + public void clear(final Graph graph, final Configuration configuration) throws Exception { + if (graph != null) + graph.close(); + + // in the even the graph is persisted we need to clean up + final String graphLocation = null != configuration ? configuration.getString(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, null) : null; + if (graphLocation != null) { + final File f = new File(graphLocation); + f.delete(); + } + } + + @Override + public Set getImplementations() { + return IMPLEMENTATION; + } + + /** + * Determines if a test requires TinkerGraph persistence to be configured with graph location and format. + */ + protected static boolean requiresPersistence(final Class test, final String testMethodName) { + return test == GraphTest.class && testMethodName.equals("shouldPersistDataOnClose"); + } + + /** + * Determines if a test requires a different cardinality as the default or not. + */ + protected static boolean requiresListCardinalityAsDefault(final LoadGraphWith.GraphData loadGraphWith, + final Class test, final String testMethodName) { + return loadGraphWith == LoadGraphWith.GraphData.CREW + || (test == StarGraphTest.class && testMethodName.equals("shouldAttachWithCreateMethod")) + || (test == DetachedGraphTest.class && testMethodName.equals("testAttachableCreateMethod")); + } + + /** + * Some tests require special configuration for TinkerGraph to properly configure the id manager. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromTest(final Class test, final String testMethodName) { + if (test.equals(GraphTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentations"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentations"); + }}; + + final Set testsThatNeedUuidIdManager = new HashSet(){{ + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentations"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentation"); + add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentations"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + else if (testsThatNeedUuidIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.UUID; + } else if (test.equals(IoEdgeTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteEdge[graphson-v1]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v1]"); + add("shouldReadWriteDetachedEdge[graphson-v1]"); + add("shouldReadWriteEdge[graphson-v2]"); + add("shouldReadWriteDetachedEdgeAsReference[graphson-v2]"); + add("shouldReadWriteDetachedEdge[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } else if (test.equals(IoVertexTest.class)) { + final Set testsThatNeedLongIdManager = new HashSet(){{ + add("shouldReadWriteVertexWithBOTHEdges[graphson-v1]"); + add("shouldReadWriteVertexWithINEdges[graphson-v1]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v1]"); + add("shouldReadWriteVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v1]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v1]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v1]"); + add("shouldReadWriteVertexWithBOTHEdges[graphson-v2]"); + add("shouldReadWriteVertexWithINEdges[graphson-v2]"); + add("shouldReadWriteVertexWithOUTEdges[graphson-v2]"); + add("shouldReadWriteVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexNoEdges[graphson-v2]"); + add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v2]"); + add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v2]"); + }}; + + if (testsThatNeedLongIdManager.contains(testMethodName)) + return TinkerGraph.DefaultIdManager.LONG; + } + + return TinkerGraph.DefaultIdManager.ANY; + } + + /** + * Test that load with specific graph data can be configured with a specific id manager as the data type to + * be used in the test for that graph is known. + */ + protected TinkerGraph.DefaultIdManager selectIdMakerFromGraphData(final LoadGraphWith.GraphData loadGraphWith) { + if (null == loadGraphWith) return TinkerGraph.DefaultIdManager.ANY; + if (loadGraphWith.equals(LoadGraphWith.GraphData.CLASSIC)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.MODERN)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.CREW)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.GRATEFUL)) + return TinkerGraph.DefaultIdManager.INTEGER; + else if (loadGraphWith.equals(LoadGraphWith.GraphData.SINK)) + return TinkerGraph.DefaultIdManager.INTEGER; + else + throw new IllegalStateException(String.format("Need to define a new %s for %s", TinkerGraph.IdManager.class.getName(), loadGraphWith.name())); + } +} diff --git a/neptune-tinkerpop/build.sh b/neptune-tinkerpop/build.sh index f92c0fd..f1f0661 100755 --- a/neptune-tinkerpop/build.sh +++ b/neptune-tinkerpop/build.sh @@ -2,7 +2,7 @@ runDir=$(pwd) -versions=("3.6.2" "3.7.2") +versions=("3.4.11" "3.5.2" "3.6.2" "3.6.5" "3.7.1" "3.7.2") for version in "${versions[@]}"; do ( cd $version diff --git a/neptune-tinkerpop/gremlin-core-3.4.11-patches.zip b/neptune-tinkerpop/gremlin-core-3.4.11-patches.zip new file mode 100644 index 0000000000000000000000000000000000000000..634f3c9adfcf7a2c6c968bfc7b694ec33c4f0c59 GIT binary patch literal 7826 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%0AKmk-NYqbZ}m1w+p{->`0lEh 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 literal 0 HcmV?d00001 diff --git a/neptune-tinkerpop/gremlin-core-3.6.2-patches.zip b/neptune-tinkerpop/gremlin-core-3.6.2-patches.zip index c3d38ff5b78700786ce654dfe820990b4b4bb011..6ebd9ae466f13d5419d4669fa07dc7ac78b7d671 100644 GIT binary patch delta 122 zcmexs@z-L*9VX_R!gnX%XUb!?JXXIsfLWIrEYQG~2ojhaz$~))2b&ZxSWr|1tO_V7 lwt0>S7aLe`rBn@AAc|%o5>Y0}HH_ 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