/* * 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.structure.util.detached; import org.apache.tinkerpop.gremlin.AbstractGremlinTest; import org.apache.tinkerpop.gremlin.FeatureRequirement; import org.apache.tinkerpop.gremlin.FeatureRequirementSet; import org.apache.tinkerpop.gremlin.LoadGraphWith; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.apache.tinkerpop.gremlin.structure.util.Attachable; import org.apache.tinkerpop.gremlin.structure.util.ElementHelper; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; import org.junit.Test; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Stephen Mallette (http://stephen.genoprime.com) */ public class DetachedVertexTest extends AbstractGremlinTest { @Test @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldIteratePropertiesOnDetached() { final Vertex v = graph.addVertex("name", "daniel", "favoriteColor", "red", "state", "happy"); final Vertex detached = DetachedFactory.detach(v, true); assertEquals("daniel", detached.properties("name").next().value()); detached.properties().forEachRemaining(p -> { if (p.key().equals("name")) assertEquals("daniel", p.value()); else if (p.key().equals("favoriteColor")) assertEquals("red", p.value()); else if (p.key().equals("state")) assertEquals("happy", p.value()); else fail("Should be one of the expected keys"); }); } @Test @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldHashAndEqualCorrectly() { final Vertex v = graph.addVertex(); final Set<Vertex> set = new HashSet<>(); for (int i = 0; i < 100; i++) { set.add(DetachedFactory.detach(v, true)); set.add(DetachedFactory.detach(v, false)); set.add(v); } assertEquals(1, set.size()); } @Test @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldNotConstructNewWithSomethingAlreadyDetached() { final Vertex v = graph.addVertex(); final DetachedVertex dv = DetachedFactory.detach(v, true); assertSame(dv, DetachedFactory.detach(dv, true)); } @Test @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldConstructDetachedVertex() { final Vertex v = graph.addVertex("test", "123"); final DetachedVertex detachedVertex = DetachedFactory.detach(v, true); assertEquals(v.id(), detachedVertex.id()); assertEquals(v.label(), detachedVertex.label()); assertEquals("123", detachedVertex.value("test")); assertEquals(1, IteratorUtils.count(detachedVertex.properties())); } @Test @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldConstructDetachedVertexAsReference() { final Vertex v = graph.addVertex("test", "123", "test", "321"); final DetachedVertex detachedVertex = DetachedFactory.detach(v, false); assertEquals(v.id(), detachedVertex.id()); assertEquals(v.label(), detachedVertex.label()); assertEquals(0, IteratorUtils.count(detachedVertex.properties())); } @Test @LoadGraphWith(LoadGraphWith.GraphData.CREW) public void shouldDetachVertexWithMultiPropertiesAndMetaProperties() { final DetachedVertex v1 = DetachedFactory.detach(convertToVertex(graph, "marko"), true); assertEquals("person", v1.label()); assertEquals(2, v1.keys().size()); v1.properties("location").forEachRemaining(vp -> { assertTrue(vp instanceof DetachedVertexProperty); if (vp.value().equals("san diego")) { assertEquals(1997, (int) vp.value("startTime")); assertEquals(2001, (int) vp.value("endTime")); assertEquals(2, (int) IteratorUtils.count(vp.properties())); } else if (vp.value().equals("santa cruz")) { assertEquals(2001, (int) vp.value("startTime")); assertEquals(2004, (int) vp.value("endTime")); assertEquals(2, (int) IteratorUtils.count(vp.properties())); } else if (vp.value().equals("brussels")) { assertEquals(2004, (int) vp.value("startTime")); assertEquals(2005, (int) vp.value("endTime")); assertEquals(2, (int) IteratorUtils.count(vp.properties())); } else if (vp.value().equals("santa fe")) { assertEquals(2005, (int) vp.value("startTime")); assertEquals(1, (int) IteratorUtils.count(vp.properties())); } else { fail("Found a value that should be there"); } }); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldEvaluateToEqual() { assertTrue(DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true).equals(DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true))); assertTrue(DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true).equals(g.V(convertToVertexId("marko")).next())); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldHaveSameHashCode() { assertEquals(DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true).hashCode(), DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true).hashCode()); assertEquals(DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true).hashCode(), g.V(convertToVertexId("marko")).next().hashCode()); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldAttachToGraph() { final Vertex toDetach = g.V(convertToVertexId("josh")).next(); final DetachedVertex detachedVertex = DetachedFactory.detach(toDetach, true); final Vertex attached = detachedVertex.attach(Attachable.Method.get(graph)); assertEquals(toDetach, attached); assertFalse(attached instanceof DetachedVertex); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldAttachToVertex() { final Vertex toDetach = g.V(convertToVertexId("josh")).next(); final DetachedVertex detachedVertex = DetachedFactory.detach(toDetach, true); final Vertex attached = detachedVertex.attach(Attachable.Method.get(toDetach)); assertEquals(toDetach, attached); assertFalse(attached instanceof DetachedVertex); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = Graph.Features.EdgePropertyFeatures.FEATURE_INTEGER_VALUES) public void shouldNotEvaluateToEqualDifferentId() { final DetachedVertex originalMarko = DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true); final Vertex secondMarko = graph.addVertex("name", "marko", "age", 29); assertFalse(DetachedFactory.detach(secondMarko, true).equals(originalMarko)); } @Test public void shouldConstructDetachedVertexFromParts() { final Map<String, Object> properties = new HashMap<>(); final Map<String, Object> propX1 = new HashMap<>(); propX1.put("value", "a"); propX1.put("id", 123); propX1.put("label", "x"); final Map<String, Object> propX2 = new HashMap<>(); propX2.put("value", "c"); propX2.put("id", 124); propX2.put("label", "x"); properties.put("x", Arrays.asList(propX1, propX2)); final Map<String, Object> propY1 = new HashMap<>(); propY1.put("value", "b"); propY1.put("id", 125); propY1.put("label", "y"); final Map<String, Object> propY2 = new HashMap<>(); propY2.put("value", "d"); propY2.put("id", 126); propY2.put("label", "y"); properties.put("y", Arrays.asList(propY1, propY2)); final DetachedVertex dv = new DetachedVertex(1, "test", properties); assertEquals(1, dv.id()); assertEquals("test", dv.label()); final List<VertexProperty<Object>> propertyX = IteratorUtils.list(dv.properties("x")); assertEquals(2, propertyX.size()); assertTrue(propertyX.stream().allMatch(p -> p.label().equals(p.key()) && (p.id().equals(123) || p.id().equals(124)) && (p.value().equals("a") || p.value().equals("c")) && !p.properties().hasNext())); } @Test public void shouldConstructDetachedVertexFromPartsWithPropertiesOnProperties() { final Map<String, Object> properties = new HashMap<>(); final Map<String, Object> propX1 = new HashMap<>(); propX1.put("value", "a"); propX1.put("id", 123); propX1.put("label", "x"); propX1.put("properties", ElementHelper.asMap("propX1a", "a", "propX11", 1, "same", 123.01d, "extra", "something")); final Map<String, Object> propX2 = new HashMap<>(); propX2.put("value", "c"); propX2.put("id", 124); propX2.put("label", "x"); properties.put("x", Arrays.asList(propX1, propX2)); final Map<String, Object> propY1 = new HashMap<>(); propY1.put("value", "b"); propY1.put("id", 125); propY1.put("label", ""); final Map<String, Object> propY2 = new HashMap<>(); propY2.put("value", "d"); propY2.put("id", 126); propY2.put("label", "y"); properties.put("y", Arrays.asList(propY1, propY2)); final DetachedVertex dv = new DetachedVertex(1, "test", properties); assertEquals(1, dv.id()); assertEquals("test", dv.label()); final List<VertexProperty<Object>> propertyX = IteratorUtils.list(dv.properties("x")); assertEquals(2, propertyX.size()); assertTrue(propertyX.stream().allMatch(p -> p.label().equals(p.key()) && (p.id().equals(123) || p.id().equals(124)) && (p.value().equals("a") || p.value().equals("c")))); // there should be only one with properties on properties final VertexProperty<?> propertyOnProperty = propertyX.stream().filter(p -> p.properties().hasNext()).findAny().get(); assertEquals("a", propertyOnProperty.properties("propX1a").next().value()); assertEquals(1, propertyOnProperty.properties("propX11").next().value()); assertEquals(123.01d, propertyOnProperty.properties("same").next().value()); assertEquals("something", propertyOnProperty.properties("extra").next().value()); assertEquals(4, IteratorUtils.count(propertyOnProperty.properties())); } @Test(expected = IllegalStateException.class) @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldNotAllowAddEdge() { final Vertex v = graph.addVertex(); final DetachedVertex detachedVertex = DetachedFactory.detach(v, true); detachedVertex.addEdge("test", null); } @Test(expected = IllegalStateException.class) @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldNotAllowSetProperty() { final Vertex v = graph.addVertex(); final DetachedVertex detachedVertex = DetachedFactory.detach(v, true); detachedVertex.property(VertexProperty.Cardinality.single, "test", "test"); } @Test(expected = IllegalStateException.class) @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldNotAllowRemove() { final Vertex v = graph.addVertex(); final DetachedVertex detachedVertex = DetachedFactory.detach(v, true); detachedVertex.remove(); } @Test(expected = IllegalStateException.class) @LoadGraphWith(LoadGraphWith.GraphData.CREW) public void shouldNotBeAbleToCallPropertyIfThereAreMultipleProperties() { DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true).property("location"); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldBeAbleToCallPropertyIfThereIsASingleProperty() { final DetachedVertex dv = DetachedFactory.detach(g.V(convertToVertexId("marko")).next(), true); assertEquals("marko", dv.property("name").value()); assertEquals(29, dv.property("age").value()); } @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY) public void shouldCreateVertex() { final DetachedVertex detachedVertex = new DetachedVertex(23, "dog", Collections.emptyMap()); detachedVertex.attach(Attachable.Method.create(graph)); assertEquals(7, IteratorUtils.count(graph.vertices())); final AtomicInteger dogTimes = new AtomicInteger(0); graph.vertices().forEachRemaining(vertex -> { if (vertex.label().equals("dog")) { dogTimes.incrementAndGet(); } }); assertEquals(1, dogTimes.get()); } }