diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/src/main/java/com/arangodb/ArangoGraph.java index 7a9a8d63c..873405cda 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/src/main/java/com/arangodb/ArangoGraph.java @@ -23,6 +23,7 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; import java.util.Collection; @@ -131,6 +132,20 @@ public interface ArangoGraph extends ArangoSerializationAccessor { */ GraphEntity addVertexCollection(String name) throws ArangoDBException; + /** + * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be + * created. + * + * @param name Name of the vertex collection + * @param options additional options + * @return information about the graph + * @throws ArangoDBException + * @see API + * Documentation + * @since ArangoDB 3.9 + */ + GraphEntity addVertexCollection(String name, VertexCollectionCreateOptions options) throws ArangoDBException; + /** * Returns a {@code ArangoVertexCollection} instance for the given vertex collection name. * diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/src/main/java/com/arangodb/async/ArangoGraphAsync.java index 34bd0d5f3..17cb45a95 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -24,6 +24,7 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -129,6 +130,19 @@ CompletableFuture createGraph( */ CompletableFuture addVertexCollection(final String name); + /** + * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be + * created. + * + * @param name The name of the collection + * @param options additional options + * @return information about the graph + * @see API + * Documentation + * @since ArangoDB 3.9 + */ + CompletableFuture addVertexCollection(final String name, final VertexCollectionCreateOptions options); + /** * Returns a handler of the vertex collection by the given name * diff --git a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java b/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java index 449f55ec3..23777f933 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java +++ b/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java @@ -27,6 +27,7 @@ import com.arangodb.entity.GraphEntity; import com.arangodb.internal.InternalArangoGraph; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; import java.util.Collection; import java.util.Objects; @@ -82,7 +83,12 @@ public CompletableFuture> getVertexCollections() { @Override public CompletableFuture addVertexCollection(final String name) { - return executor.execute(addVertexCollectionRequest(name), addVertexCollectionResponseDeserializer()); + return addVertexCollection(name, new VertexCollectionCreateOptions()); + } + + @Override + public CompletableFuture addVertexCollection(final String name, final VertexCollectionCreateOptions options) { + return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/entity/EdgeDefinition.java b/src/main/java/com/arangodb/entity/EdgeDefinition.java index 598ef58d3..d48c78951 100644 --- a/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -32,6 +32,7 @@ public class EdgeDefinition { private String collection; private Collection from; private Collection to; + private Options options; public String getCollection() { return collection; @@ -60,4 +61,24 @@ public EdgeDefinition to(final String... to) { return this; } + public Collection getSatellites() { + return options.satellites; + } + + /** + * @param satellites collection names that will be used to create SatelliteCollections + * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element + * must be a valid collection name. The collection type cannot be modified later. + * @return this + * @since ArangoDB 3.9.0 + */ + public EdgeDefinition satellites(final String... satellites) { + options = new Options(); + options.satellites = Arrays.asList(satellites); + return this; + } + + private static class Options { + private Collection satellites; + } } diff --git a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java b/src/main/java/com/arangodb/internal/ArangoGraphImpl.java index 7c9a79ba4..c72c86fc8 100644 --- a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoGraphImpl.java @@ -27,6 +27,7 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; import java.util.Collection; @@ -86,7 +87,12 @@ public Collection getVertexCollections() throws ArangoDBException { @Override public GraphEntity addVertexCollection(final String name) throws ArangoDBException { - return executor.execute(addVertexCollectionRequest(name), addVertexCollectionResponseDeserializer()); + return addVertexCollection(name, new VertexCollectionCreateOptions()); + } + + @Override + public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) throws ArangoDBException { + return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/src/main/java/com/arangodb/internal/InternalArangoGraph.java index 5e71cb60c..a03e090e6 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -88,9 +88,9 @@ protected ResponseDeserializer> getVertexCollectionsResponseD }.getType()); } - protected Request addVertexCollectionRequest(final String name) { + protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); - request.setBody(util().serialize(OptionsBuilder.build(new VertexCollectionCreateOptions(), name))); + request.setBody(util().serialize(OptionsBuilder.build(options, name))); return request; } diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/src/main/java/com/arangodb/model/GraphCreateOptions.java index 1494e4128..25e681fec 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -190,6 +190,22 @@ public GraphCreateOptions smartGraphAttribute(final String smartGraphAttribute) return this; } + public Collection getSatellites() { + return getOptions().getSatellites(); + } + + /** + * @param satellites collection names that will be used to create SatelliteCollections + * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element + * must be a valid collection name. The collection type cannot be modified later. + * @return options + * @since ArangoDB 3.9.0 + */ + public GraphCreateOptions satellites(final String... satellites) { + getOptions().setSatellites(satellites); + return this; + } + private SmartOptions getOptions() { if (options == null) { options = new SmartOptions(); @@ -203,6 +219,7 @@ public static class SmartOptions { private Integer numberOfShards; private String smartGraphAttribute; private Boolean isDisjoint; + private Collection satellites; public SmartOptions() { super(); @@ -257,6 +274,13 @@ public void setIsDisjoint(final Boolean isDisjoint) { this.isDisjoint = isDisjoint; } + public Collection getSatellites() { + return satellites; + } + + public void setSatellites(final String... satellites) { + this.satellites = Arrays.asList(satellites); + } } } diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index 213f6ac2f..2806daf3a 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -20,12 +20,16 @@ package com.arangodb.model; +import java.util.Arrays; +import java.util.Collection; + /** * @author Mark Vollmary */ public class VertexCollectionCreateOptions { private String collection; + private Options options; public VertexCollectionCreateOptions() { super(); @@ -44,4 +48,25 @@ protected VertexCollectionCreateOptions collection(final String collection) { return this; } + public Collection getSatellites() { + return options.satellites; + } + + /** + * @param satellites collection names that will be used to create SatelliteCollections + * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element + * must be a valid collection name. The collection type cannot be modified later. + * @return options + * @since ArangoDB 3.9.0 + */ + public VertexCollectionCreateOptions satellites(final String... satellites) { + options = new Options(); + options.satellites = Arrays.asList(satellites); + return this; + } + + private static class Options { + private Collection satellites; + } + } diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/src/test/java/com/arangodb/ArangoGraphTest.java index 2ba0c95fa..ffa5f7651 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/ArangoGraphTest.java @@ -24,6 +24,7 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -185,6 +186,26 @@ public void addVertexCollection() { graph.vertexCollection(VERTEX_COL_4).drop(); } + @Test + public void addSatelliteVertexCollection() { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 9)); + + String v1Name = "vertex-" + rnd(); + + ArangoGraph g = db.graph(GRAPH_NAME + rnd()); + g.create(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)); + + Collection vertexCollections = g.getVertexCollections(); + assertThat(vertexCollections, hasItems(v1Name)); + assertThat(db.collection(v1Name).getProperties().getSatellite(), is(true)); + + // revert + g.drop(); + } + @Test public void getEdgeCollections() { final Collection edgeCollections = graph.getEdgeDefinitions(); @@ -223,6 +244,35 @@ public void addEdgeDefinition() { graph.removeEdgeDefinition(EDGE_COL_3); } + @Test + public void addSatelliteEdgeDefinition() { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 9)); + + String eName = "edge-" + rnd(); + String v1Name = "vertex-" + rnd(); + String v2Name = "vertex-" + rnd(); + EdgeDefinition ed = new EdgeDefinition().collection(eName).from(v1Name).to(v2Name).satellites(v1Name); + + ArangoGraph g = db.graph(GRAPH_NAME + rnd()); + g.create(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.addEdgeDefinition(ed); + final GraphEntity ge = g.getInfo(); + assertThat(ge, is(notNullValue())); + final Collection edgeDefinitions = ge.getEdgeDefinitions(); + assertThat(edgeDefinitions.size(), is(1)); + EdgeDefinition e = edgeDefinitions.iterator().next(); + assertThat(e.getCollection(), is(eName)); + assertThat(e.getFrom(), hasItem(v1Name)); + assertThat(e.getTo(), hasItem(v2Name)); + + assertThat(db.collection(v1Name).getProperties().getSatellite(), is(true)); + + // revert + g.drop(); + } + @Test public void replaceEdgeDefinition() { final GraphEntity g = graph @@ -277,6 +327,33 @@ public void smartGraph() { assertThat(g.getNumberOfShards(), is(2)); } + @Test + public void hybridSmartGraph() { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + assumeTrue((isAtLeastVersion(3, 9))); + + final Collection edgeDefinitions = new ArrayList<>(); + String eName = "hybridSmartGraph-edge-" + rnd(); + String v1Name = "hybridSmartGraph-vertex-" + rnd(); + String v2Name = "hybridSmartGraph-vertex-" + rnd(); + edgeDefinitions.add(new EdgeDefinition().collection(eName).from(v1Name).to(v2Name)); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions() + .satellites(eName, v1Name) + .isSmart(true).smartGraphAttribute("test").replicationFactor(2).numberOfShards(2)); + + assertThat(g, is(notNullValue())); + assertThat(g.getIsSmart(), is(true)); + assertThat(g.getSmartGraphAttribute(), is("test")); + assertThat(g.getNumberOfShards(), is(2)); + + assertThat(db.collection(eName).getProperties().getSatellite(), is(true)); + assertThat(db.collection(v1Name).getProperties().getSatellite(), is(true)); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor(), is(2)); + } + @Test public void disjointSmartGraph() { assumeTrue(isEnterprise()); @@ -297,6 +374,33 @@ public void disjointSmartGraph() { assertThat(g.getNumberOfShards(), is(2)); } + @Test + public void hybridDisjointSmartGraph() { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + assumeTrue((isAtLeastVersion(3, 9))); + + final Collection edgeDefinitions = new ArrayList<>(); + String eName = "hybridDisjointSmartGraph-edge-" + rnd(); + String v1Name = "hybridDisjointSmartGraph-vertex-" + rnd(); + String v2Name = "hybridDisjointSmartGraph-vertex-" + rnd(); + edgeDefinitions.add(new EdgeDefinition().collection(eName).from(v1Name).to(v2Name)); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions() + .satellites(v1Name) + .isSmart(true).isDisjoint(true).smartGraphAttribute("test").replicationFactor(2).numberOfShards(2)); + + assertThat(g, is(notNullValue())); + assertThat(g.getIsSmart(), is(true)); + assertThat(g.getIsDisjoint(), is(true)); + assertThat(g.getSmartGraphAttribute(), is("test")); + assertThat(g.getNumberOfShards(), is(2)); + + assertThat(db.collection(v1Name).getProperties().getSatellite(), is(true)); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor(), is(2)); + } + @Test public void drop() { final String edgeCollection = "edge_" + rnd(); diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/src/test/java/com/arangodb/async/ArangoGraphTest.java index 60563e051..7551b2931 100644 --- a/src/test/java/com/arangodb/async/ArangoGraphTest.java +++ b/src/test/java/com/arangodb/async/ArangoGraphTest.java @@ -25,6 +25,7 @@ import com.arangodb.entity.GraphEntity; import com.arangodb.entity.ServerRole; import com.arangodb.model.GraphCreateOptions; +import com.arangodb.model.VertexCollectionCreateOptions; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; @@ -36,8 +37,8 @@ import java.util.concurrent.ExecutionException; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; import static org.junit.Assume.assumeTrue; /** @@ -161,6 +162,26 @@ public void addVertexCollection() throws InterruptedException, ExecutionExceptio setup(); } + @Test + public void addSatelliteVertexCollection() throws ExecutionException, InterruptedException { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 9)); + + String v1Name = "vertex-" + rnd(); + + ArangoGraphAsync g = db.graph(GRAPH_NAME + rnd()); + g.createGraph(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)).get(); + + Collection vertexCollections = g.getVertexCollections().get(); + assertThat(vertexCollections, hasItems(v1Name)); + assertThat(db.collection(v1Name).getProperties().get().getSatellite(), is(true)); + + // revert + g.drop().get(); + } + @Test public void getEdgeCollections() throws InterruptedException, ExecutionException { final Collection edgeCollections = db.graph(GRAPH_NAME).getEdgeDefinitions().get(); @@ -198,6 +219,35 @@ public void addEdgeDefinition() throws InterruptedException, ExecutionException setup(); } + @Test + public void addSatelliteEdgeDefinition() throws ExecutionException, InterruptedException { + assumeTrue(isCluster()); + assumeTrue(isEnterprise()); + assumeTrue(isAtLeastVersion(3, 9)); + + String eName = "edge-" + rnd(); + String v1Name = "vertex-" + rnd(); + String v2Name = "vertex-" + rnd(); + EdgeDefinition ed = new EdgeDefinition().collection(eName).from(v1Name).to(v2Name).satellites(v1Name); + + ArangoGraphAsync g = db.graph(GRAPH_NAME + rnd()); + g.createGraph(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.addEdgeDefinition(ed).get(); + final GraphEntity ge = g.getInfo().get(); + assertThat(ge, is(notNullValue())); + final Collection edgeDefinitions = ge.getEdgeDefinitions(); + assertThat(edgeDefinitions.size(), is(1)); + EdgeDefinition e = edgeDefinitions.iterator().next(); + assertThat(e.getCollection(), is(eName)); + assertThat(e.getFrom(), hasItem(v1Name)); + assertThat(e.getTo(), hasItem(v2Name)); + + assertThat(db.collection(v1Name).getProperties().get().getSatellite(), is(true)); + + // revert + g.drop().get(); + } + @Test public void replaceEdgeDefinition() throws InterruptedException, ExecutionException { final GraphEntity graph = db.graph(GRAPH_NAME) @@ -245,8 +295,8 @@ public void smartGraph() throws InterruptedException, ExecutionException { edgeDefinitions .add(new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3)); final GraphEntity graph = db.createGraph(GRAPH_NAME + "_smart", edgeDefinitions, - new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").replicationFactor(REPLICATION_FACTOR) - .numberOfShards(NUMBER_OF_SHARDS)) + new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").replicationFactor(REPLICATION_FACTOR) + .numberOfShards(NUMBER_OF_SHARDS)) .get(); assertThat(graph, is(notNullValue())); assertThat(graph.getIsSmart(), is(true)); @@ -257,13 +307,67 @@ public void smartGraph() throws InterruptedException, ExecutionException { } } + @Test + public void hybridSmartGraph() throws ExecutionException, InterruptedException { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + assumeTrue((isAtLeastVersion(3, 9))); + + final Collection edgeDefinitions = new ArrayList<>(); + String eName = "hybridSmartGraph-edge-" + rnd(); + String v1Name = "hybridSmartGraph-vertex-" + rnd(); + String v2Name = "hybridSmartGraph-vertex-" + rnd(); + edgeDefinitions.add(new EdgeDefinition().collection(eName).from(v1Name).to(v2Name)); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions() + .satellites(eName, v1Name) + .isSmart(true).smartGraphAttribute("test").replicationFactor(2).numberOfShards(2)).get(); + + assertThat(g, is(notNullValue())); + assertThat(g.getIsSmart(), is(true)); + assertThat(g.getSmartGraphAttribute(), is("test")); + assertThat(g.getNumberOfShards(), is(2)); + + assertThat(db.collection(eName).getProperties().get().getSatellite(), is(true)); + assertThat(db.collection(v1Name).getProperties().get().getSatellite(), is(true)); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor(), is(2)); + } + + @Test + public void hybridDisjointSmartGraph() throws ExecutionException, InterruptedException { + assumeTrue(isEnterprise()); + assumeTrue(isCluster()); + assumeTrue((isAtLeastVersion(3, 9))); + + final Collection edgeDefinitions = new ArrayList<>(); + String eName = "hybridDisjointSmartGraph-edge-" + rnd(); + String v1Name = "hybridDisjointSmartGraph-vertex-" + rnd(); + String v2Name = "hybridDisjointSmartGraph-vertex-" + rnd(); + edgeDefinitions.add(new EdgeDefinition().collection(eName).from(v1Name).to(v2Name)); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions() + .satellites(v1Name) + .isSmart(true).isDisjoint(true).smartGraphAttribute("test").replicationFactor(2).numberOfShards(2)).get(); + + assertThat(g, is(notNullValue())); + assertThat(g.getIsSmart(), is(true)); + assertThat(g.getIsDisjoint(), is(true)); + assertThat(g.getSmartGraphAttribute(), is("test")); + assertThat(g.getNumberOfShards(), is(2)); + + assertThat(db.collection(v1Name).getProperties().get().getSatellite(), is(true)); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor(), is(2)); + } + @Test public void drop() throws InterruptedException, ExecutionException { final String edgeCollection = "edge_drop"; final String vertexCollection = "vertex_drop"; final String graph = GRAPH_NAME + "_drop"; final GraphEntity result = db.graph(graph).create(Collections - .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))) + .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))) .get(); assertThat(result, is(notNullValue())); db.graph(graph).drop().get(); @@ -277,7 +381,7 @@ public void dropPlusDropCollections() throws InterruptedException, ExecutionExce final String vertexCollection = "vertex_dropC"; final String graph = GRAPH_NAME + "_dropC"; final GraphEntity result = db.graph(graph).create(Collections - .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))) + .singleton(new EdgeDefinition().collection(edgeCollection).from(vertexCollection).to(vertexCollection))) .get(); assertThat(result, is(notNullValue())); db.graph(graph).drop(true).get(); diff --git a/src/test/java/com/arangodb/async/BaseTest.java b/src/test/java/com/arangodb/async/BaseTest.java index 13ade24d7..819ef79cb 100644 --- a/src/test/java/com/arangodb/async/BaseTest.java +++ b/src/test/java/com/arangodb/async/BaseTest.java @@ -27,6 +27,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -60,6 +61,10 @@ public static void shutdown() throws InterruptedException, ExecutionException { arangoDB = null; } + static String rnd() { + return UUID.randomUUID().toString(); + } + protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor, final int patch) throws InterruptedException, ExecutionException { return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, patch);