/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tinkerpop.gremlin.process.traversal.step.filter; import org.apache.tinkerpop.gremlin.LoadGraphWith; import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest; import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner; import org.apache.tinkerpop.gremlin.process.traversal.Order; import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.Scope; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.dedup; import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select; import static org.apache.tinkerpop.gremlin.structure.Column.values; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Marko A. Rodriguez (http://markorodriguez.com) * @author Stephen Mallette (http://stephen.genoprime.com) * @author Daniel Kuppitz (http://gremlin.guru) */ @RunWith(GremlinProcessRunner.class) public abstract class DedupTest extends AbstractGremlinProcessTest { public abstract Traversal<Vertex, String> get_g_V_both_dedup_name(); public abstract Traversal<Vertex, String> get_g_V_both_hasXlabel_softwareX_dedup_byXlangX_name(); public abstract Traversal<Vertex, String> get_g_V_both_name_order_byXa_bX_dedup_value(); public abstract Traversal<Vertex, String> get_g_V_both_both_name_dedup(); public abstract Traversal<Vertex, Vertex> get_g_V_both_both_dedup(); public abstract Traversal<Vertex, Vertex> get_g_V_both_both_dedup_byXlabelX(); public abstract Traversal<Vertex, Map<String, List<Double>>> get_g_V_group_byXlabelX_byXbothE_weight_dedup_foldX(); public abstract Traversal<Vertex, Map<String, Vertex>> get_g_V_asXaX_both_asXbX_dedupXa_bX_byXlabelX_selectXa_bX(); public abstract Traversal<Vertex, Path> get_g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_dedupXa_bX_path(); public abstract Traversal<Vertex, String> get_g_V_outE_asXeX_inV_asXvX_selectXeX_order_byXweight_incrX_selectXvX_valuesXnameX_dedup(); public abstract Traversal<Vertex, String> get_g_V_both_both_dedup_byXoutE_countX_name(); public abstract Traversal<Vertex, String> get_g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold(); public abstract Traversal<Vertex, Map<String, String>> get_g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold(); public abstract Traversal<Vertex, Long> get_g_V_groupCount_selectXvaluesX_unfold_dedup(); public abstract Traversal<Vertex, Collection<String>> get_g_V_asXaX_repeatXbothX_timesX3X_emit_name_asXbX_group_byXselectXaXX_byXselectXbX_dedup_order_foldX_selectXvaluesX_unfold_dedup(); public abstract Traversal<Vertex, Long> get_g_V_repeatXdedupX_timesX2X_count(); @Test @LoadGraphWith(MODERN) public void g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold() { final Traversal<Vertex, String> traversal = get_g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold(); printTraversalForm(traversal); checkResults(Arrays.asList("marko", "josh", "peter"), traversal); } @Test @LoadGraphWith(MODERN) public void g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold() { final Traversal<Vertex, Map<String, String>> traversal = get_g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold(); printTraversalForm(traversal); checkResults(makeMapList(2, "x", "lop", "y", "marko", "x", "lop", "y", "josh", "x", "lop", "y", "peter", "x", "vadas", "y", "marko", "x", "josh", "y", "marko", "x", "ripple", "y", "josh"), traversal); } @Test @LoadGraphWith(MODERN) public void g_V_both_dedup_name() { final Traversal<Vertex, String> traversal = get_g_V_both_dedup_name(); printTraversalForm(traversal); final List<String> names = traversal.toList(); assertEquals(6, names.size()); assertTrue(names.contains("marko")); assertTrue(names.contains("vadas")); assertTrue(names.contains("lop")); assertTrue(names.contains("josh")); assertTrue(names.contains("ripple")); assertTrue(names.contains("peter")); assertFalse(traversal.hasNext()); } @Test @LoadGraphWith(MODERN) public void g_V_both_hasXlabel_softwareX_dedup_byXlangX_name() { final Traversal<Vertex, String> traversal = get_g_V_both_hasXlabel_softwareX_dedup_byXlangX_name(); printTraversalForm(traversal); final List<String> names = traversal.toList(); assertEquals(1, names.size()); assertTrue(names.contains("lop") || names.contains("ripple")); assertFalse(traversal.hasNext()); } @Test @LoadGraphWith(MODERN) public void g_V_both_name_order_byXa_bX_dedup_value() { final Traversal<Vertex, String> traversal = get_g_V_both_name_order_byXa_bX_dedup_value(); printTraversalForm(traversal); final List<String> names = traversal.toList(); assertEquals(6, names.size()); assertEquals("josh", names.get(0)); assertEquals("lop", names.get(1)); assertEquals("marko", names.get(2)); assertEquals("peter", names.get(3)); assertEquals("ripple", names.get(4)); assertEquals("vadas", names.get(5)); assertFalse(traversal.hasNext()); } @Test @LoadGraphWith(MODERN) public void g_V_both_both_name_dedup() { final Traversal<Vertex, String> traversal = get_g_V_both_both_name_dedup(); printTraversalForm(traversal); checkResults(Arrays.asList("marko", "vadas", "josh", "peter", "lop", "ripple"), traversal); } @Test @LoadGraphWith(MODERN) public void g_V_both_both_dedup() { final Traversal<Vertex, Vertex> traversal = get_g_V_both_both_dedup(); printTraversalForm(traversal); checkResults(Arrays.asList( convertToVertex(graph, "marko"), convertToVertex(graph, "vadas"), convertToVertex(graph, "josh"), convertToVertex(graph, "peter"), convertToVertex(graph, "lop"), convertToVertex(graph, "ripple")), traversal); } @Test @LoadGraphWith(MODERN) public void g_V_both_both_dedup_byXlabelX() { final Traversal<Vertex, Vertex> traversal = get_g_V_both_both_dedup_byXlabelX(); printTraversalForm(traversal); final List<Vertex> vertices = traversal.toList(); assertEquals(2, vertices.size()); } @Test @LoadGraphWith(MODERN) public void g_V_group_byXlabelX_byXbothE_weight_dedup_foldX() { final Traversal<Vertex, Map<String, List<Double>>> traversal = get_g_V_group_byXlabelX_byXbothE_weight_dedup_foldX(); printTraversalForm(traversal); assertTrue(traversal.hasNext()); final Map<String, List<Double>> map = traversal.next(); assertFalse(traversal.hasNext()); assertEquals(2, map.size()); assertEquals(3, map.get("software").size()); assertEquals(4, map.get("person").size()); assertTrue(map.get("software").contains(0.2)); assertTrue(map.get("software").contains(0.4)); assertTrue(map.get("software").contains(1.0)); // assertTrue(map.get("person").contains(0.2)); assertTrue(map.get("person").contains(0.4)); assertTrue(map.get("person").contains(0.5)); assertTrue(map.get("person").contains(1.0)); } @Test @LoadGraphWith(MODERN) public void g_V_asXaX_both_asXbX_dedupXa_bX_byXlabelX_selectXa_bX() { final Traversal<Vertex, Map<String, Vertex>> traversal = get_g_V_asXaX_both_asXbX_dedupXa_bX_byXlabelX_selectXa_bX(); printTraversalForm(traversal); int personPersonCounter = 0; int personSoftwareCounter = 0; int softwarePersonCounter = 0; while (traversal.hasNext()) { final Map<String, Vertex> map = traversal.next(); assertEquals(2, map.size()); if (map.get("a").label().equals("person") && map.get("b").label().equals("person")) personPersonCounter++; else if (map.get("a").label().equals("person") && map.get("b").label().equals("software")) personSoftwareCounter++; else if (map.get("a").label().equals("software") && map.get("b").label().equals("person")) softwarePersonCounter++; else fail("Bad result type: " + map); } assertEquals(1, personPersonCounter); assertEquals(1, personSoftwareCounter); assertEquals(1, softwarePersonCounter); } @Test @LoadGraphWith(MODERN) public void g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_dedupXa_bX_path() { final Traversal<Vertex, Path> traversal = get_g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_dedupXa_bX_path(); printTraversalForm(traversal); int counter = 0; final Set<List<Vertex>> results = new HashSet<>(); while (traversal.hasNext()) { final Path path = traversal.next(); assertEquals(3, path.size()); assertTrue(results.add(Arrays.asList(path.get("a"), path.get("b")))); counter++; } assertEquals(4, counter); assertEquals(4, results.size()); } @Test @LoadGraphWith(MODERN) public void g_V_outE_asXeX_inV_asXvX_selectXeX_order_byXweight_incrX_selectXvX_valuesXnameX_dedup() { final Traversal<Vertex, String> traversal = get_g_V_outE_asXeX_inV_asXvX_selectXeX_order_byXweight_incrX_selectXvX_valuesXnameX_dedup(); printTraversalForm(traversal); final List<String> names = traversal.toList(); assertEquals(4, names.size()); assertTrue(names.contains("vadas")); assertTrue(names.contains("lop")); assertTrue(names.contains("josh")); assertTrue(names.contains("ripple")); assertFalse(traversal.hasNext()); } @Test @LoadGraphWith(MODERN) public void g_V_both_both_dedup_byXoutE_countX_name() { final Traversal<Vertex, String> traversal = get_g_V_both_both_dedup_byXoutE_countX_name(); printTraversalForm(traversal); final List<String> names = traversal.toList(); assertEquals(4, names.size()); assertTrue(names.contains("josh")); assertTrue(names.contains("peter")); assertTrue(names.contains("marko")); // the 4th is vadas, ripple, or lop assertEquals(4, new HashSet<>(names).size()); } @Test @LoadGraphWith(MODERN) public void g_V_groupCount_selectXvaluesX_unfold_dedup() { final Traversal<Vertex, Long> traversal = get_g_V_groupCount_selectXvaluesX_unfold_dedup(); printTraversalForm(traversal); checkResults(Collections.singletonList(1L), traversal); } @Test @LoadGraphWith(MODERN) public void g_V_asXaX_repeatXbothX_timesX3X_emit_asXbX_group_byXselectXaXX_byXselectXbX_dedup_order_byXidX_foldX_selectXvaluesX_unfold_dedup() { final Traversal<Vertex, Collection<String>> traversal = get_g_V_asXaX_repeatXbothX_timesX3X_emit_name_asXbX_group_byXselectXaXX_byXselectXbX_dedup_order_foldX_selectXvaluesX_unfold_dedup(); printTraversalForm(traversal); final List<String> vertices = new ArrayList<>(traversal.next()); assertFalse(traversal.hasNext()); assertEquals(6, vertices.size()); assertEquals("josh", vertices.get(0)); assertEquals("lop", vertices.get(1)); assertEquals("marko", vertices.get(2)); assertEquals("peter", vertices.get(3)); assertEquals("ripple", vertices.get(4)); assertEquals("vadas", vertices.get(5)); } @Test @LoadGraphWith(MODERN) public void g_V_repeatXdedupX_timesX2X_count() { final Traversal<Vertex, Long> traversal = get_g_V_repeatXdedupX_timesX2X_count(); printTraversalForm(traversal); assertEquals(0L, traversal.next().longValue()); assertFalse(traversal.hasNext()); } public static class Traversals extends DedupTest { @Override public Traversal<Vertex, String> get_g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold() { return g.V().out().in().values("name").fold().dedup(Scope.local).unfold(); } @Override public Traversal<Vertex, Map<String, String>> get_g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold() { return g.V().out().as("x").in().as("y").select("x", "y").by("name").fold().dedup(Scope.local, "x", "y").unfold(); } @Override public Traversal<Vertex, String> get_g_V_both_dedup_name() { return g.V().both().dedup().values("name"); } @Override public Traversal<Vertex, String> get_g_V_both_hasXlabel_softwareX_dedup_byXlangX_name() { return g.V().both().has(T.label, "software").dedup().by("lang").values("name"); } @Override public Traversal<Vertex, String> get_g_V_both_name_order_byXa_bX_dedup_value() { return g.V().both().<String>properties("name").order().by((a, b) -> a.value().compareTo(b.value())).dedup().value(); } @Override public Traversal<Vertex, String> get_g_V_both_both_name_dedup() { return g.V().both().both().<String>values("name").dedup(); } @Override public Traversal<Vertex, Vertex> get_g_V_both_both_dedup() { return g.V().both().both().dedup(); } @Override public Traversal<Vertex, Vertex> get_g_V_both_both_dedup_byXlabelX() { return g.V().both().both().dedup().by(T.label); } @Override public Traversal<Vertex, Map<String, List<Double>>> get_g_V_group_byXlabelX_byXbothE_weight_dedup_foldX() { return g.V().<String, List<Double>>group().by(T.label).by(bothE().values("weight").dedup().fold()); } @Override public Traversal<Vertex, Map<String, Vertex>> get_g_V_asXaX_both_asXbX_dedupXa_bX_byXlabelX_selectXa_bX() { return g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b"); } @Override public Traversal<Vertex, Path> get_g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_dedupXa_bX_path() { return g.V().as("a").out("created").as("b").in("created").as("c").dedup("a", "b").path(); } @Override public Traversal<Vertex, String> get_g_V_outE_asXeX_inV_asXvX_selectXeX_order_byXweight_incrX_selectXvX_valuesXnameX_dedup() { return g.V().outE().as("e").inV().as("v").select("e").order().by("weight", Order.incr).select("v").<String>values("name").dedup(); } @Override public Traversal<Vertex, String> get_g_V_both_both_dedup_byXoutE_countX_name() { return g.V().both().both().dedup().by(__.outE().count()).values("name"); } @Override public Traversal<Vertex, Long> get_g_V_groupCount_selectXvaluesX_unfold_dedup() { return g.V().groupCount().select(values).<Long>unfold().dedup(); } @Override public Traversal<Vertex, Collection<String>> get_g_V_asXaX_repeatXbothX_timesX3X_emit_name_asXbX_group_byXselectXaXX_byXselectXbX_dedup_order_foldX_selectXvaluesX_unfold_dedup() { return g.V().as("a").repeat(both()).times(3).emit().values("name").as("b").group().by(select("a")).by(select("b").dedup().order().fold()).select(values).<Collection<String>>unfold().dedup(); } @Override public Traversal<Vertex, Long> get_g_V_repeatXdedupX_timesX2X_count() { return g.V().repeat(dedup()).times(2).count(); } } }